diff --git a/.gitattributes b/.gitattributes index 7bb09cfbffe..d42177674f6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,7 +19,6 @@ binding.gyp linguist-generated=true src/python/grpcio/grpc_core_dependencies.py linguist-generated=true src/ruby/ext/grpc/rb_grpc_imports.generated.h linguist-generated=true src/ruby/ext/grpc/rb_grpc_imports.generated.c linguist-generated=true -test/core/end2end/end2end_tests.cc linguist-generated=true test/core/security/grpc_tls_credentials_options_comparator_test.cc linguist-generated=true test/core/surface/public_headers_must_be_c89.c linguist-generated=true tools/doxygen/Doxyfile.c++.internal linguist-generated=true diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c7891e28f0..fcbec1106cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -780,24 +780,10 @@ protobuf_generate_grpc_cpp_with_import_path_correction( if(gRPC_BUILD_TESTS) add_custom_target(buildtests_c) - add_dependencies(buildtests_c bad_server_response_test) - if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - add_dependencies(buildtests_c bad_ssl_alpn_test) - endif() - if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - add_dependencies(buildtests_c bad_ssl_cert_test) - endif() - add_dependencies(buildtests_c connection_refused_test) - if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - add_dependencies(buildtests_c dualstack_socket_test) - endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c fd_conservation_posix_test) endif() - add_dependencies(buildtests_c goaway_server_test) - add_dependencies(buildtests_c invalid_call_argument_test) add_dependencies(buildtests_c multiple_server_queues_test) - add_dependencies(buildtests_c no_server_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX OR _gRPC_PLATFORM_WINDOWS) add_dependencies(buildtests_c pollset_windows_starvation_test) endif() @@ -850,6 +836,13 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx aws_request_signer_test) add_dependencies(buildtests_cxx b64_test) add_dependencies(buildtests_cxx backoff_test) + add_dependencies(buildtests_cxx bad_server_response_test) + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx bad_ssl_alpn_test) + endif() + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx bad_ssl_cert_test) + endif() add_dependencies(buildtests_cxx bad_streaming_id_bad_client_test) add_dependencies(buildtests_cxx badreq_bad_client_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -915,11 +908,13 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx compression_test) add_dependencies(buildtests_cxx concurrent_connectivity_test) add_dependencies(buildtests_cxx connection_prefix_bad_client_test) + add_dependencies(buildtests_cxx connection_refused_test) add_dependencies(buildtests_cxx connectivity_state_test) add_dependencies(buildtests_cxx context_allocator_end2end_test) add_dependencies(buildtests_cxx context_list_test) add_dependencies(buildtests_cxx context_test) add_dependencies(buildtests_cxx core_configuration_test) + add_dependencies(buildtests_cxx core_end2end_tests) add_dependencies(buildtests_cxx cpp_impl_of_test) add_dependencies(buildtests_cxx cpu_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -931,6 +926,9 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx dns_resolver_cooldown_test) add_dependencies(buildtests_cxx dns_resolver_test) add_dependencies(buildtests_cxx dual_ref_counted_test) + if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + add_dependencies(buildtests_cxx dualstack_socket_test) + endif() add_dependencies(buildtests_cxx duplicate_header_bad_client_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx end2end_binder_transport_test) @@ -978,6 +976,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx fuzzing_event_engine_test) endif() add_dependencies(buildtests_cxx generic_end2end_test) + add_dependencies(buildtests_cxx goaway_server_test) add_dependencies(buildtests_cxx google_c2p_resolver_test) add_dependencies(buildtests_cxx google_mesh_ca_certificate_provider_factory_test) add_dependencies(buildtests_cxx graceful_shutdown_test) @@ -1033,6 +1032,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx interceptor_list_test) add_dependencies(buildtests_cxx interop_client) add_dependencies(buildtests_cxx interop_server) + add_dependencies(buildtests_cxx invalid_call_argument_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX OR _gRPC_PLATFORM_WINDOWS) add_dependencies(buildtests_cxx iocp_test) endif() @@ -1074,6 +1074,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx mpscq_test) endif() add_dependencies(buildtests_cxx no_destruct_test) + add_dependencies(buildtests_cxx no_server_test) add_dependencies(buildtests_cxx nonblocking_test) add_dependencies(buildtests_cxx notification_test) add_dependencies(buildtests_cxx num_external_connectivity_watchers_test) @@ -1411,160 +1412,6 @@ if(gRPC_INSTALL) ) endif() -if(gRPC_BUILD_TESTS) - -add_library(end2end_tests - test/core/end2end/cq_verifier.cc - test/core/end2end/data/client_certs.cc - test/core/end2end/data/server1_cert.cc - test/core/end2end/data/server1_key.cc - test/core/end2end/data/test_root_cert.cc - test/core/end2end/end2end_test_utils.cc - test/core/end2end/end2end_tests.cc - test/core/end2end/fixtures/http_proxy_fixture.cc - test/core/end2end/fixtures/local_util.cc - test/core/end2end/fixtures/proxy.cc - test/core/end2end/tests/authority_not_supported.cc - test/core/end2end/tests/bad_hostname.cc - test/core/end2end/tests/bad_ping.cc - test/core/end2end/tests/binary_metadata.cc - test/core/end2end/tests/call_creds.cc - test/core/end2end/tests/call_host_override.cc - test/core/end2end/tests/cancel_after_accept.cc - test/core/end2end/tests/cancel_after_client_done.cc - test/core/end2end/tests/cancel_after_invoke.cc - test/core/end2end/tests/cancel_after_round_trip.cc - test/core/end2end/tests/cancel_before_invoke.cc - test/core/end2end/tests/cancel_in_a_vacuum.cc - test/core/end2end/tests/cancel_with_status.cc - test/core/end2end/tests/channelz.cc - test/core/end2end/tests/client_streaming.cc - test/core/end2end/tests/compressed_payload.cc - test/core/end2end/tests/connectivity.cc - test/core/end2end/tests/default_host.cc - test/core/end2end/tests/disappearing_server.cc - test/core/end2end/tests/empty_batch.cc - test/core/end2end/tests/filter_causes_close.cc - test/core/end2end/tests/filter_context.cc - test/core/end2end/tests/filter_init_fails.cc - test/core/end2end/tests/filter_latency.cc - test/core/end2end/tests/filter_status_code.cc - test/core/end2end/tests/filtered_metadata.cc - test/core/end2end/tests/graceful_server_shutdown.cc - test/core/end2end/tests/grpc_authz.cc - test/core/end2end/tests/high_initial_seqno.cc - test/core/end2end/tests/hpack_size.cc - test/core/end2end/tests/invoke_large_request.cc - test/core/end2end/tests/keepalive_timeout.cc - test/core/end2end/tests/large_metadata.cc - test/core/end2end/tests/max_concurrent_streams.cc - test/core/end2end/tests/max_connection_age.cc - test/core/end2end/tests/max_connection_idle.cc - test/core/end2end/tests/max_message_length.cc - test/core/end2end/tests/negative_deadline.cc - test/core/end2end/tests/no_logging.cc - test/core/end2end/tests/no_op.cc - test/core/end2end/tests/payload.cc - test/core/end2end/tests/ping.cc - test/core/end2end/tests/ping_pong_streaming.cc - test/core/end2end/tests/proxy_auth.cc - test/core/end2end/tests/registered_call.cc - test/core/end2end/tests/request_with_flags.cc - test/core/end2end/tests/request_with_payload.cc - test/core/end2end/tests/resource_quota_server.cc - test/core/end2end/tests/retry.cc - test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc - test/core/end2end/tests/retry_cancel_during_delay.cc - test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc - test/core/end2end/tests/retry_cancellation.cc - test/core/end2end/tests/retry_disabled.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc - test/core/end2end/tests/retry_lb_drop.cc - test/core/end2end/tests/retry_lb_fail.cc - test/core/end2end/tests/retry_non_retriable_status.cc - test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc - test/core/end2end/tests/retry_per_attempt_recv_timeout.cc - test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc - test/core/end2end/tests/retry_recv_initial_metadata.cc - test/core/end2end/tests/retry_recv_message.cc - test/core/end2end/tests/retry_recv_message_replay.cc - test/core/end2end/tests/retry_recv_trailing_metadata_error.cc - test/core/end2end/tests/retry_send_initial_metadata_refs.cc - test/core/end2end/tests/retry_send_op_fails.cc - test/core/end2end/tests/retry_send_recv_batch.cc - test/core/end2end/tests/retry_server_pushback_delay.cc - test/core/end2end/tests/retry_server_pushback_disabled.cc - test/core/end2end/tests/retry_streaming.cc - test/core/end2end/tests/retry_streaming_after_commit.cc - test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc - test/core/end2end/tests/retry_throttled.cc - test/core/end2end/tests/retry_too_many_attempts.cc - test/core/end2end/tests/retry_transparent_goaway.cc - test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc - test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc - test/core/end2end/tests/retry_unref_before_finish.cc - test/core/end2end/tests/retry_unref_before_recv.cc - test/core/end2end/tests/server_finishes_request.cc - test/core/end2end/tests/server_streaming.cc - test/core/end2end/tests/shutdown_finishes_calls.cc - test/core/end2end/tests/shutdown_finishes_tags.cc - test/core/end2end/tests/simple_delayed_request.cc - test/core/end2end/tests/simple_metadata.cc - test/core/end2end/tests/simple_request.cc - test/core/end2end/tests/streaming_error_response.cc - test/core/end2end/tests/trailing_metadata.cc - test/core/end2end/tests/write_buffering.cc - test/core/end2end/tests/write_buffering_at_end.cc - test/core/util/test_lb_policies.cc -) - -target_compile_features(end2end_tests PUBLIC cxx_std_14) - -set_target_properties(end2end_tests PROPERTIES - VERSION ${gRPC_CORE_VERSION} - SOVERSION ${gRPC_CORE_SOVERSION} -) - -if(WIN32 AND MSVC) - set_target_properties(end2end_tests PROPERTIES COMPILE_PDB_NAME "end2end_tests" - COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - ) - if(gRPC_INSTALL) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/end2end_tests.pdb - DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL - ) - endif() -endif() - -target_include_directories(end2end_tests - PUBLIC $ $ - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - third_party/googletest/googletest/include - third_party/googletest/googletest - third_party/googletest/googlemock/include - third_party/googletest/googlemock -) -target_link_libraries(end2end_tests - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_authorization_provider - grpc_test_util -) - - -endif() add_library(gpr src/core/lib/config/config_vars.cc @@ -4985,42 +4832,11 @@ if(gRPC_INSTALL) endif() -if(gRPC_BUILD_TESTS) - -add_executable(bad_server_response_test - test/core/end2end/bad_server_response_test.cc - test/core/end2end/cq_verifier.cc -) -target_compile_features(bad_server_response_test PUBLIC cxx_std_14) -target_include_directories(bad_server_response_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(bad_server_response_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - add_executable(bad_ssl_alpn_test - test/core/bad_ssl/bad_ssl_test.cc - test/core/end2end/cq_verifier.cc + add_executable(fd_conservation_posix_test + test/core/iomgr/fd_conservation_posix_test.cc test/core/util/cmdline.cc test/core/util/fuzzer_util.cc test/core/util/grpc_profiler.cc @@ -5034,8 +4850,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) test/core/util/subprocess_windows.cc test/core/util/tracer_util.cc ) - target_compile_features(bad_ssl_alpn_test PUBLIC cxx_std_14) - target_include_directories(bad_ssl_alpn_test + target_compile_features(fd_conservation_posix_test PUBLIC cxx_std_14) + target_include_directories(fd_conservation_posix_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -5049,7 +4865,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_ZLIB_INCLUDE_DIR} ) - target_link_libraries(bad_ssl_alpn_test + target_link_libraries(fd_conservation_posix_test ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_ZLIB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} @@ -5060,26 +4876,42 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) endif() endif() if(gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - add_executable(bad_ssl_cert_test - test/core/bad_ssl/bad_ssl_test.cc - test/core/end2end/cq_verifier.cc - test/core/util/cmdline.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc - test/core/util/histogram.cc - test/core/util/mock_endpoint.cc - test/core/util/parse_hexstring.cc - test/core/util/passthru_endpoint.cc - test/core/util/resolve_localhost_ip46.cc - test/core/util/slice_splitter.cc - test/core/util/subprocess_posix.cc - test/core/util/subprocess_windows.cc - test/core/util/tracer_util.cc +add_executable(multiple_server_queues_test + test/core/end2end/multiple_server_queues_test.cc +) +target_compile_features(multiple_server_queues_test PUBLIC cxx_std_14) +target_include_directories(multiple_server_queues_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} +) + +target_link_libraries(multiple_server_queues_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX OR _gRPC_PLATFORM_WINDOWS) + + add_executable(pollset_windows_starvation_test + test/core/iomgr/pollset_windows_starvation_test.cc ) - target_compile_features(bad_ssl_cert_test PUBLIC cxx_std_14) - target_include_directories(bad_ssl_cert_test + target_compile_features(pollset_windows_starvation_test PUBLIC cxx_std_14) + target_include_directories(pollset_windows_starvation_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -5093,7 +4925,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_ZLIB_INCLUDE_DIR} ) - target_link_libraries(bad_ssl_cert_test + target_link_libraries(pollset_windows_starvation_test ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_ZLIB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} @@ -5105,263 +4937,8 @@ endif() endif() if(gRPC_BUILD_TESTS) -add_executable(connection_refused_test - test/core/end2end/connection_refused_test.cc - test/core/end2end/cq_verifier.cc -) -target_compile_features(connection_refused_test PUBLIC cxx_std_14) -target_include_directories(connection_refused_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(connection_refused_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() -if(gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - - add_executable(dualstack_socket_test - test/core/end2end/cq_verifier.cc - test/core/end2end/dualstack_socket_test.cc - ) - target_compile_features(dualstack_socket_test PUBLIC cxx_std_14) - target_include_directories(dualstack_socket_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - ) - - target_link_libraries(dualstack_socket_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - ) - - -endif() -endif() -if(gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - - add_executable(fd_conservation_posix_test - test/core/iomgr/fd_conservation_posix_test.cc - test/core/util/cmdline.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc - test/core/util/histogram.cc - test/core/util/mock_endpoint.cc - test/core/util/parse_hexstring.cc - test/core/util/passthru_endpoint.cc - test/core/util/resolve_localhost_ip46.cc - test/core/util/slice_splitter.cc - test/core/util/subprocess_posix.cc - test/core/util/subprocess_windows.cc - test/core/util/tracer_util.cc - ) - target_compile_features(fd_conservation_posix_test PUBLIC cxx_std_14) - target_include_directories(fd_conservation_posix_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - ) - - target_link_libraries(fd_conservation_posix_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - ) - - -endif() -endif() -if(gRPC_BUILD_TESTS) - -add_executable(goaway_server_test - test/core/end2end/cq_verifier.cc - test/core/end2end/goaway_server_test.cc -) -target_compile_features(goaway_server_test PUBLIC cxx_std_14) -target_include_directories(goaway_server_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(goaway_server_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() -if(gRPC_BUILD_TESTS) - -add_executable(invalid_call_argument_test - test/core/end2end/cq_verifier.cc - test/core/end2end/invalid_call_argument_test.cc -) -target_compile_features(invalid_call_argument_test PUBLIC cxx_std_14) -target_include_directories(invalid_call_argument_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(invalid_call_argument_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() -if(gRPC_BUILD_TESTS) - -add_executable(multiple_server_queues_test - test/core/end2end/multiple_server_queues_test.cc -) -target_compile_features(multiple_server_queues_test PUBLIC cxx_std_14) -target_include_directories(multiple_server_queues_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(multiple_server_queues_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() -if(gRPC_BUILD_TESTS) - -add_executable(no_server_test - test/core/end2end/cq_verifier.cc - test/core/end2end/no_server_test.cc -) -target_compile_features(no_server_test PUBLIC cxx_std_14) -target_include_directories(no_server_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} -) - -target_link_libraries(no_server_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) - - -endif() -if(gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX OR _gRPC_PLATFORM_WINDOWS) - - add_executable(pollset_windows_starvation_test - test/core/iomgr/pollset_windows_starvation_test.cc - ) - target_compile_features(pollset_windows_starvation_test PUBLIC cxx_std_14) - target_include_directories(pollset_windows_starvation_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - ) - - target_link_libraries(pollset_windows_starvation_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - ) - - -endif() -endif() -if(gRPC_BUILD_TESTS) - -add_executable(public_headers_must_be_c89 - test/core/surface/public_headers_must_be_c89.c +add_executable(public_headers_must_be_c89 + test/core/surface/public_headers_must_be_c89.c ) target_compile_features(public_headers_must_be_c89 PUBLIC cxx_std_14) target_include_directories(public_headers_must_be_c89 @@ -6810,15 +6387,157 @@ target_include_directories(backoff_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(backoff_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_PROTOBUF_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util -) +target_link_libraries(backoff_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(bad_server_response_test + test/core/end2end/bad_server_response_test.cc + test/core/end2end/cq_verifier.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(bad_server_response_test PUBLIC cxx_std_14) +target_include_directories(bad_server_response_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(bad_server_response_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + + add_executable(bad_ssl_alpn_test + test/core/bad_ssl/bad_ssl_test.cc + test/core/end2end/cq_verifier.cc + test/core/util/cmdline.cc + test/core/util/fuzzer_util.cc + test/core/util/grpc_profiler.cc + test/core/util/histogram.cc + test/core/util/mock_endpoint.cc + test/core/util/parse_hexstring.cc + test/core/util/passthru_endpoint.cc + test/core/util/resolve_localhost_ip46.cc + test/core/util/slice_splitter.cc + test/core/util/subprocess_posix.cc + test/core/util/subprocess_windows.cc + test/core/util/tracer_util.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc + ) + target_compile_features(bad_ssl_alpn_test PUBLIC cxx_std_14) + target_include_directories(bad_ssl_alpn_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} + ) + + target_link_libraries(bad_ssl_alpn_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + ) + + +endif() +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + + add_executable(bad_ssl_cert_test + test/core/bad_ssl/bad_ssl_test.cc + test/core/end2end/cq_verifier.cc + test/core/util/cmdline.cc + test/core/util/fuzzer_util.cc + test/core/util/grpc_profiler.cc + test/core/util/histogram.cc + test/core/util/mock_endpoint.cc + test/core/util/parse_hexstring.cc + test/core/util/passthru_endpoint.cc + test/core/util/resolve_localhost_ip46.cc + test/core/util/slice_splitter.cc + test/core/util/subprocess_posix.cc + test/core/util/subprocess_windows.cc + test/core/util/tracer_util.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc + ) + target_compile_features(bad_ssl_cert_test PUBLIC cxx_std_14) + target_include_directories(bad_ssl_cert_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} + ) + + target_link_libraries(bad_ssl_cert_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + ) +endif() endif() if(gRPC_BUILD_TESTS) @@ -9276,6 +8995,44 @@ target_link_libraries(connection_prefix_bad_client_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(connection_refused_test + test/core/end2end/connection_refused_test.cc + test/core/end2end/cq_verifier.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(connection_refused_test PUBLIC cxx_std_14) +target_include_directories(connection_refused_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(connection_refused_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) @@ -9399,8 +9156,214 @@ add_executable(context_list_test third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_compile_features(context_list_test PUBLIC cxx_std_14) -target_include_directories(context_list_test +target_compile_features(context_list_test PUBLIC cxx_std_14) +target_include_directories(context_list_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(context_list_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(context_test + test/core/promise/context_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(context_test PUBLIC cxx_std_14) +target_include_directories(context_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(context_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + gpr +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(core_configuration_test + test/core/config/core_configuration_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(core_configuration_test PUBLIC cxx_std_14) +target_include_directories(core_configuration_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(core_configuration_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(core_end2end_tests + test/core/end2end/cq_verifier.cc + test/core/end2end/end2end_test_main.cc + test/core/end2end/end2end_tests.cc + test/core/end2end/fixtures/http_proxy_fixture.cc + test/core/end2end/fixtures/local_util.cc + test/core/end2end/fixtures/proxy.cc + test/core/end2end/tests/bad_ping.cc + test/core/end2end/tests/binary_metadata.cc + test/core/end2end/tests/call_creds.cc + test/core/end2end/tests/call_host_override.cc + test/core/end2end/tests/cancel_after_accept.cc + test/core/end2end/tests/cancel_after_client_done.cc + test/core/end2end/tests/cancel_after_invoke.cc + test/core/end2end/tests/cancel_after_round_trip.cc + test/core/end2end/tests/cancel_before_invoke.cc + test/core/end2end/tests/cancel_in_a_vacuum.cc + test/core/end2end/tests/cancel_with_status.cc + test/core/end2end/tests/channelz.cc + test/core/end2end/tests/client_streaming.cc + test/core/end2end/tests/compressed_payload.cc + test/core/end2end/tests/connectivity.cc + test/core/end2end/tests/default_host.cc + test/core/end2end/tests/disappearing_server.cc + test/core/end2end/tests/empty_batch.cc + test/core/end2end/tests/filter_causes_close.cc + test/core/end2end/tests/filter_context.cc + test/core/end2end/tests/filter_init_fails.cc + test/core/end2end/tests/filtered_metadata.cc + test/core/end2end/tests/graceful_server_shutdown.cc + test/core/end2end/tests/grpc_authz.cc + test/core/end2end/tests/high_initial_seqno.cc + test/core/end2end/tests/hpack_size.cc + test/core/end2end/tests/invoke_large_request.cc + test/core/end2end/tests/keepalive_timeout.cc + test/core/end2end/tests/large_metadata.cc + test/core/end2end/tests/max_concurrent_streams.cc + test/core/end2end/tests/max_connection_age.cc + test/core/end2end/tests/max_connection_idle.cc + test/core/end2end/tests/max_message_length.cc + test/core/end2end/tests/negative_deadline.cc + test/core/end2end/tests/no_logging.cc + test/core/end2end/tests/no_op.cc + test/core/end2end/tests/payload.cc + test/core/end2end/tests/ping.cc + test/core/end2end/tests/ping_pong_streaming.cc + test/core/end2end/tests/proxy_auth.cc + test/core/end2end/tests/registered_call.cc + test/core/end2end/tests/request_with_flags.cc + test/core/end2end/tests/request_with_payload.cc + test/core/end2end/tests/resource_quota_server.cc + test/core/end2end/tests/retry.cc + test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc + test/core/end2end/tests/retry_cancel_during_delay.cc + test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc + test/core/end2end/tests/retry_cancellation.cc + test/core/end2end/tests/retry_disabled.cc + test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc + test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc + test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + test/core/end2end/tests/retry_lb_drop.cc + test/core/end2end/tests/retry_lb_fail.cc + test/core/end2end/tests/retry_non_retriable_status.cc + test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc + test/core/end2end/tests/retry_per_attempt_recv_timeout.cc + test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc + test/core/end2end/tests/retry_recv_initial_metadata.cc + test/core/end2end/tests/retry_recv_message.cc + test/core/end2end/tests/retry_recv_message_replay.cc + test/core/end2end/tests/retry_recv_trailing_metadata_error.cc + test/core/end2end/tests/retry_send_initial_metadata_refs.cc + test/core/end2end/tests/retry_send_op_fails.cc + test/core/end2end/tests/retry_send_recv_batch.cc + test/core/end2end/tests/retry_server_pushback_delay.cc + test/core/end2end/tests/retry_server_pushback_disabled.cc + test/core/end2end/tests/retry_streaming.cc + test/core/end2end/tests/retry_streaming_after_commit.cc + test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc + test/core/end2end/tests/retry_throttled.cc + test/core/end2end/tests/retry_too_many_attempts.cc + test/core/end2end/tests/retry_transparent_goaway.cc + test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc + test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc + test/core/end2end/tests/retry_unref_before_finish.cc + test/core/end2end/tests/retry_unref_before_recv.cc + test/core/end2end/tests/server_finishes_request.cc + test/core/end2end/tests/server_streaming.cc + test/core/end2end/tests/shutdown_finishes_calls.cc + test/core/end2end/tests/shutdown_finishes_tags.cc + test/core/end2end/tests/simple_delayed_request.cc + test/core/end2end/tests/simple_metadata.cc + test/core/end2end/tests/simple_request.cc + test/core/end2end/tests/streaming_error_response.cc + test/core/end2end/tests/trailing_metadata.cc + test/core/end2end/tests/write_buffering.cc + test/core/end2end/tests/write_buffering_at_end.cc + test/core/util/test_lb_policies.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(core_end2end_tests PUBLIC cxx_std_14) +target_include_directories(core_end2end_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -9419,89 +9382,17 @@ target_include_directories(context_list_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(context_list_test +target_link_libraries(core_end2end_tests ${_gRPC_BASELIB_LIBRARIES} ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ZLIB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_authorization_provider + grpc_unsecure grpc_test_util ) -endif() -if(gRPC_BUILD_TESTS) - -add_executable(context_test - test/core/promise/context_test.cc - third_party/googletest/googletest/src/gtest-all.cc - third_party/googletest/googlemock/src/gmock-all.cc -) -target_compile_features(context_test PUBLIC cxx_std_14) -target_include_directories(context_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - third_party/googletest/googletest/include - third_party/googletest/googletest - third_party/googletest/googlemock/include - third_party/googletest/googlemock - ${_gRPC_PROTO_GENS_DIR} -) - -target_link_libraries(context_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_PROTOBUF_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - gpr -) - - -endif() -if(gRPC_BUILD_TESTS) - -add_executable(core_configuration_test - test/core/config/core_configuration_test.cc - third_party/googletest/googletest/src/gtest-all.cc - third_party/googletest/googlemock/src/gmock-all.cc -) -target_compile_features(core_configuration_test PUBLIC cxx_std_14) -target_include_directories(core_configuration_test - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} - ${_gRPC_RE2_INCLUDE_DIR} - ${_gRPC_SSL_INCLUDE_DIR} - ${_gRPC_UPB_GENERATED_DIR} - ${_gRPC_UPB_GRPC_GENERATED_DIR} - ${_gRPC_UPB_INCLUDE_DIR} - ${_gRPC_XXHASH_INCLUDE_DIR} - ${_gRPC_ZLIB_INCLUDE_DIR} - third_party/googletest/googletest/include - third_party/googletest/googletest - third_party/googletest/googlemock/include - third_party/googletest/googlemock - ${_gRPC_PROTO_GENS_DIR} -) - -target_link_libraries(core_configuration_test - ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_PROTOBUF_LIBRARIES} - ${_gRPC_ZLIB_LIBRARIES} - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc -) - - endif() if(gRPC_BUILD_TESTS) @@ -9854,6 +9745,46 @@ target_link_libraries(dual_ref_counted_test ) +endif() +if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + + add_executable(dualstack_socket_test + test/core/end2end/cq_verifier.cc + test/core/end2end/dualstack_socket_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc + ) + target_compile_features(dualstack_socket_test PUBLIC cxx_std_14) + target_include_directories(dualstack_socket_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} + ) + + target_link_libraries(dualstack_socket_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + ) + + +endif() endif() if(gRPC_BUILD_TESTS) @@ -11858,6 +11789,44 @@ target_link_libraries(generic_end2end_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(goaway_server_test + test/core/end2end/cq_verifier.cc + test/core/end2end/goaway_server_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(goaway_server_test PUBLIC cxx_std_14) +target_include_directories(goaway_server_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(goaway_server_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) @@ -13064,6 +13033,7 @@ add_executable(h2_ssl_cert_test test/core/end2end/data/server1_cert.cc test/core/end2end/data/server1_key.cc test/core/end2end/data/test_root_cert.cc + test/core/end2end/end2end_tests.cc test/core/end2end/fixtures/local_util.cc test/core/end2end/h2_ssl_cert_test.cc third_party/googletest/googletest/src/gtest-all.cc @@ -14230,6 +14200,44 @@ target_link_libraries(interop_server ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(invalid_call_argument_test + test/core/end2end/cq_verifier.cc + test/core/end2end/invalid_call_argument_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(invalid_call_argument_test PUBLIC cxx_std_14) +target_include_directories(invalid_call_argument_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(invalid_call_argument_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX OR _gRPC_PLATFORM_WINDOWS) @@ -15565,6 +15573,44 @@ target_link_libraries(no_destruct_test ) +endif() +if(gRPC_BUILD_TESTS) + +add_executable(no_server_test + test/core/end2end/cq_verifier.cc + test/core/end2end/no_server_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) +target_compile_features(no_server_test PUBLIC cxx_std_14) +target_include_directories(no_server_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(no_server_test + ${_gRPC_BASELIB_LIBRARIES} + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ZLIB_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 341ddcd2b65..a36f98314ff 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -12,134 +12,6 @@ libs: - third_party/address_sorting/address_sorting_posix.c - third_party/address_sorting/address_sorting_windows.c deps: [] -- name: end2end_tests - build: private - language: c - public_headers: [] - headers: - - test/core/end2end/cq_verifier.h - - test/core/end2end/data/ssl_test_data.h - - test/core/end2end/end2end_tests.h - - test/core/end2end/fixtures/h2_oauth2_common.h - - test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h - - test/core/end2end/fixtures/h2_ssl_tls_common.h - - test/core/end2end/fixtures/h2_tls_common.h - - test/core/end2end/fixtures/http_proxy_fixture.h - - test/core/end2end/fixtures/inproc_fixture.h - - test/core/end2end/fixtures/local_util.h - - test/core/end2end/fixtures/proxy.h - - test/core/end2end/fixtures/secure_fixture.h - - test/core/end2end/fixtures/sockpair_fixture.h - - test/core/end2end/tests/cancel_test_helpers.h - - test/core/util/test_lb_policies.h - src: - - test/core/end2end/cq_verifier.cc - - test/core/end2end/data/client_certs.cc - - test/core/end2end/data/server1_cert.cc - - test/core/end2end/data/server1_key.cc - - test/core/end2end/data/test_root_cert.cc - - test/core/end2end/end2end_test_utils.cc - - test/core/end2end/end2end_tests.cc - - test/core/end2end/fixtures/http_proxy_fixture.cc - - test/core/end2end/fixtures/local_util.cc - - test/core/end2end/fixtures/proxy.cc - - test/core/end2end/tests/authority_not_supported.cc - - test/core/end2end/tests/bad_hostname.cc - - test/core/end2end/tests/bad_ping.cc - - test/core/end2end/tests/binary_metadata.cc - - test/core/end2end/tests/call_creds.cc - - test/core/end2end/tests/call_host_override.cc - - test/core/end2end/tests/cancel_after_accept.cc - - test/core/end2end/tests/cancel_after_client_done.cc - - test/core/end2end/tests/cancel_after_invoke.cc - - test/core/end2end/tests/cancel_after_round_trip.cc - - test/core/end2end/tests/cancel_before_invoke.cc - - test/core/end2end/tests/cancel_in_a_vacuum.cc - - test/core/end2end/tests/cancel_with_status.cc - - test/core/end2end/tests/channelz.cc - - test/core/end2end/tests/client_streaming.cc - - test/core/end2end/tests/compressed_payload.cc - - test/core/end2end/tests/connectivity.cc - - test/core/end2end/tests/default_host.cc - - test/core/end2end/tests/disappearing_server.cc - - test/core/end2end/tests/empty_batch.cc - - test/core/end2end/tests/filter_causes_close.cc - - test/core/end2end/tests/filter_context.cc - - test/core/end2end/tests/filter_init_fails.cc - - test/core/end2end/tests/filter_latency.cc - - test/core/end2end/tests/filter_status_code.cc - - test/core/end2end/tests/filtered_metadata.cc - - test/core/end2end/tests/graceful_server_shutdown.cc - - test/core/end2end/tests/grpc_authz.cc - - test/core/end2end/tests/high_initial_seqno.cc - - test/core/end2end/tests/hpack_size.cc - - test/core/end2end/tests/invoke_large_request.cc - - test/core/end2end/tests/keepalive_timeout.cc - - test/core/end2end/tests/large_metadata.cc - - test/core/end2end/tests/max_concurrent_streams.cc - - test/core/end2end/tests/max_connection_age.cc - - test/core/end2end/tests/max_connection_idle.cc - - test/core/end2end/tests/max_message_length.cc - - test/core/end2end/tests/negative_deadline.cc - - test/core/end2end/tests/no_logging.cc - - test/core/end2end/tests/no_op.cc - - test/core/end2end/tests/payload.cc - - test/core/end2end/tests/ping.cc - - test/core/end2end/tests/ping_pong_streaming.cc - - test/core/end2end/tests/proxy_auth.cc - - test/core/end2end/tests/registered_call.cc - - test/core/end2end/tests/request_with_flags.cc - - test/core/end2end/tests/request_with_payload.cc - - test/core/end2end/tests/resource_quota_server.cc - - test/core/end2end/tests/retry.cc - - test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc - - test/core/end2end/tests/retry_cancel_during_delay.cc - - test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc - - test/core/end2end/tests/retry_cancellation.cc - - test/core/end2end/tests/retry_disabled.cc - - test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc - - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc - - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc - - test/core/end2end/tests/retry_lb_drop.cc - - test/core/end2end/tests/retry_lb_fail.cc - - test/core/end2end/tests/retry_non_retriable_status.cc - - test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc - - test/core/end2end/tests/retry_per_attempt_recv_timeout.cc - - test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc - - test/core/end2end/tests/retry_recv_initial_metadata.cc - - test/core/end2end/tests/retry_recv_message.cc - - test/core/end2end/tests/retry_recv_message_replay.cc - - test/core/end2end/tests/retry_recv_trailing_metadata_error.cc - - test/core/end2end/tests/retry_send_initial_metadata_refs.cc - - test/core/end2end/tests/retry_send_op_fails.cc - - test/core/end2end/tests/retry_send_recv_batch.cc - - test/core/end2end/tests/retry_server_pushback_delay.cc - - test/core/end2end/tests/retry_server_pushback_disabled.cc - - test/core/end2end/tests/retry_streaming.cc - - test/core/end2end/tests/retry_streaming_after_commit.cc - - test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc - - test/core/end2end/tests/retry_throttled.cc - - test/core/end2end/tests/retry_too_many_attempts.cc - - test/core/end2end/tests/retry_transparent_goaway.cc - - test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc - - test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc - - test/core/end2end/tests/retry_unref_before_finish.cc - - test/core/end2end/tests/retry_unref_before_recv.cc - - test/core/end2end/tests/server_finishes_request.cc - - test/core/end2end/tests/server_streaming.cc - - test/core/end2end/tests/shutdown_finishes_calls.cc - - test/core/end2end/tests/shutdown_finishes_tags.cc - - test/core/end2end/tests/simple_delayed_request.cc - - test/core/end2end/tests/simple_metadata.cc - - test/core/end2end/tests/simple_request.cc - - test/core/end2end/tests/streaming_error_response.cc - - test/core/end2end/tests/trailing_metadata.cc - - test/core/end2end/tests/write_buffering.cc - - test/core/end2end/tests/write_buffering_at_end.cc - - test/core/util/test_lb_policies.cc - deps: - - grpc_authorization_provider - - grpc_test_util - name: gpr build: all language: c @@ -4185,118 +4057,6 @@ libs: deps: - grpc++ targets: -- name: bad_server_response_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/bad_server_response_test.cc - - test/core/end2end/cq_verifier.cc - deps: - - grpc_test_util -- name: bad_ssl_alpn_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - - test/core/util/cmdline.h - - test/core/util/evaluate_args_test_util.h - - test/core/util/fuzzer_util.h - - test/core/util/grpc_profiler.h - - test/core/util/histogram.h - - test/core/util/mock_authorization_endpoint.h - - test/core/util/mock_endpoint.h - - test/core/util/parse_hexstring.h - - test/core/util/passthru_endpoint.h - - test/core/util/resolve_localhost_ip46.h - - test/core/util/slice_splitter.h - - test/core/util/subprocess.h - - test/core/util/tracer_util.h - src: - - test/core/bad_ssl/bad_ssl_test.cc - - test/core/end2end/cq_verifier.cc - - test/core/util/cmdline.cc - - test/core/util/fuzzer_util.cc - - test/core/util/grpc_profiler.cc - - test/core/util/histogram.cc - - test/core/util/mock_endpoint.cc - - test/core/util/parse_hexstring.cc - - test/core/util/passthru_endpoint.cc - - test/core/util/resolve_localhost_ip46.cc - - test/core/util/slice_splitter.cc - - test/core/util/subprocess_posix.cc - - test/core/util/subprocess_windows.cc - - test/core/util/tracer_util.cc - deps: - - grpc_test_util - platforms: - - linux - - posix - - mac -- name: bad_ssl_cert_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - - test/core/util/cmdline.h - - test/core/util/evaluate_args_test_util.h - - test/core/util/fuzzer_util.h - - test/core/util/grpc_profiler.h - - test/core/util/histogram.h - - test/core/util/mock_authorization_endpoint.h - - test/core/util/mock_endpoint.h - - test/core/util/parse_hexstring.h - - test/core/util/passthru_endpoint.h - - test/core/util/resolve_localhost_ip46.h - - test/core/util/slice_splitter.h - - test/core/util/subprocess.h - - test/core/util/tracer_util.h - src: - - test/core/bad_ssl/bad_ssl_test.cc - - test/core/end2end/cq_verifier.cc - - test/core/util/cmdline.cc - - test/core/util/fuzzer_util.cc - - test/core/util/grpc_profiler.cc - - test/core/util/histogram.cc - - test/core/util/mock_endpoint.cc - - test/core/util/parse_hexstring.cc - - test/core/util/passthru_endpoint.cc - - test/core/util/resolve_localhost_ip46.cc - - test/core/util/slice_splitter.cc - - test/core/util/subprocess_posix.cc - - test/core/util/subprocess_windows.cc - - test/core/util/tracer_util.cc - deps: - - grpc_test_util - platforms: - - linux - - posix - - mac -- name: connection_refused_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/connection_refused_test.cc - - test/core/end2end/cq_verifier.cc - deps: - - grpc_test_util -- name: dualstack_socket_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/cq_verifier.cc - - test/core/end2end/dualstack_socket_test.cc - deps: - - grpc_test_util - platforms: - - linux - - posix - - mac - name: fd_conservation_posix_test build: test language: c @@ -4334,26 +4094,6 @@ targets: - linux - posix - mac -- name: goaway_server_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/cq_verifier.cc - - test/core/end2end/goaway_server_test.cc - deps: - - grpc_test_util -- name: invalid_call_argument_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/cq_verifier.cc - - test/core/end2end/invalid_call_argument_test.cc - deps: - - grpc_test_util - name: multiple_server_queues_test build: test language: c @@ -4362,16 +4102,6 @@ targets: - test/core/end2end/multiple_server_queues_test.cc deps: - grpc_test_util -- name: no_server_test - build: test - language: c - headers: - - test/core/end2end/cq_verifier.h - src: - - test/core/end2end/cq_verifier.cc - - test/core/end2end/no_server_test.cc - deps: - - grpc_test_util - name: pollset_windows_starvation_test build: test language: c @@ -4905,21 +4635,146 @@ targets: deps: - grpc_test_util uses_polling: false -- name: auth_property_iterator_test +- name: auth_property_iterator_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/cpp/common/auth_property_iterator_test.cc + deps: + - grpc++_test_util + uses_polling: false +- name: authorization_matchers_test + gtest: true + build: test + language: c++ + headers: + - test/core/util/cmdline.h + - test/core/util/evaluate_args_test_util.h + - test/core/util/fuzzer_util.h + - test/core/util/grpc_profiler.h + - test/core/util/histogram.h + - test/core/util/mock_authorization_endpoint.h + - test/core/util/mock_endpoint.h + - test/core/util/parse_hexstring.h + - test/core/util/passthru_endpoint.h + - test/core/util/resolve_localhost_ip46.h + - test/core/util/slice_splitter.h + - test/core/util/subprocess.h + - test/core/util/tracer_util.h + src: + - test/core/security/authorization_matchers_test.cc + - test/core/util/cmdline.cc + - test/core/util/fuzzer_util.cc + - test/core/util/grpc_profiler.cc + - test/core/util/histogram.cc + - test/core/util/mock_endpoint.cc + - test/core/util/parse_hexstring.cc + - test/core/util/passthru_endpoint.cc + - test/core/util/resolve_localhost_ip46.cc + - test/core/util/slice_splitter.cc + - test/core/util/subprocess_posix.cc + - test/core/util/subprocess_windows.cc + - test/core/util/tracer_util.cc + deps: + - grpc_test_util +- name: authorization_policy_provider_test + gtest: true + build: test + language: c++ + headers: [] + src: + - src/cpp/server/authorization_policy_provider.cc + - test/cpp/server/authorization_policy_provider_test.cc + deps: + - grpc++ + - grpc_authorization_provider + - grpc_test_util +- name: avl_test + gtest: true + build: test + language: c++ + headers: + - src/core/lib/avl/avl.h + - src/core/lib/gpr/useful.h + src: + - test/core/avl/avl_test.cc + deps: + - absl/strings:strings + - absl/types:variant + uses_polling: false +- name: aws_request_signer_test + gtest: true + build: test + language: c++ + headers: + - test/core/util/cmdline.h + - test/core/util/evaluate_args_test_util.h + - test/core/util/fuzzer_util.h + - test/core/util/grpc_profiler.h + - test/core/util/histogram.h + - test/core/util/mock_authorization_endpoint.h + - test/core/util/mock_endpoint.h + - test/core/util/parse_hexstring.h + - test/core/util/passthru_endpoint.h + - test/core/util/resolve_localhost_ip46.h + - test/core/util/slice_splitter.h + - test/core/util/subprocess.h + - test/core/util/tracer_util.h + src: + - test/core/security/aws_request_signer_test.cc + - test/core/util/cmdline.cc + - test/core/util/fuzzer_util.cc + - test/core/util/grpc_profiler.cc + - test/core/util/histogram.cc + - test/core/util/mock_endpoint.cc + - test/core/util/parse_hexstring.cc + - test/core/util/passthru_endpoint.cc + - test/core/util/resolve_localhost_ip46.cc + - test/core/util/slice_splitter.cc + - test/core/util/subprocess_posix.cc + - test/core/util/subprocess_windows.cc + - test/core/util/tracer_util.cc + deps: + - grpc_test_util +- name: b64_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/slice/b64_test.cc + deps: + - grpc_test_util + uses_polling: false +- name: backoff_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/backoff/backoff_test.cc + deps: + - grpc_test_util + uses_polling: false +- name: bad_server_response_test gtest: true build: test language: c++ - headers: [] + headers: + - test/core/end2end/cq_verifier.h src: - - test/cpp/common/auth_property_iterator_test.cc + - test/core/end2end/bad_server_response_test.cc + - test/core/end2end/cq_verifier.cc deps: - - grpc++_test_util - uses_polling: false -- name: authorization_matchers_test + - grpc_test_util +- name: bad_ssl_alpn_test gtest: true build: test language: c++ headers: + - test/core/end2end/cq_verifier.h - test/core/util/cmdline.h - test/core/util/evaluate_args_test_util.h - test/core/util/fuzzer_util.h @@ -4934,7 +4789,8 @@ targets: - test/core/util/subprocess.h - test/core/util/tracer_util.h src: - - test/core/security/authorization_matchers_test.cc + - test/core/bad_ssl/bad_ssl_test.cc + - test/core/end2end/cq_verifier.cc - test/core/util/cmdline.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc @@ -4949,36 +4805,16 @@ targets: - test/core/util/tracer_util.cc deps: - grpc_test_util -- name: authorization_policy_provider_test - gtest: true - build: test - language: c++ - headers: [] - src: - - src/cpp/server/authorization_policy_provider.cc - - test/cpp/server/authorization_policy_provider_test.cc - deps: - - grpc++ - - grpc_authorization_provider - - grpc_test_util -- name: avl_test - gtest: true - build: test - language: c++ - headers: - - src/core/lib/avl/avl.h - - src/core/lib/gpr/useful.h - src: - - test/core/avl/avl_test.cc - deps: - - absl/strings:strings - - absl/types:variant - uses_polling: false -- name: aws_request_signer_test + platforms: + - linux + - posix + - mac +- name: bad_ssl_cert_test gtest: true build: test language: c++ headers: + - test/core/end2end/cq_verifier.h - test/core/util/cmdline.h - test/core/util/evaluate_args_test_util.h - test/core/util/fuzzer_util.h @@ -4993,7 +4829,8 @@ targets: - test/core/util/subprocess.h - test/core/util/tracer_util.h src: - - test/core/security/aws_request_signer_test.cc + - test/core/bad_ssl/bad_ssl_test.cc + - test/core/end2end/cq_verifier.cc - test/core/util/cmdline.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc @@ -5008,26 +4845,10 @@ targets: - test/core/util/tracer_util.cc deps: - grpc_test_util -- name: b64_test - gtest: true - build: test - language: c++ - headers: [] - src: - - test/core/slice/b64_test.cc - deps: - - grpc_test_util - uses_polling: false -- name: backoff_test - gtest: true - build: test - language: c++ - headers: [] - src: - - test/core/backoff/backoff_test.cc - deps: - - grpc_test_util - uses_polling: false + platforms: + - linux + - posix + - mac - name: bad_streaming_id_bad_client_test gtest: true build: test @@ -6225,6 +6046,17 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util +- name: connection_refused_test + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + src: + - test/core/end2end/connection_refused_test.cc + - test/core/end2end/cq_verifier.cc + deps: + - grpc_test_util - name: connectivity_state_test gtest: true build: test @@ -6330,6 +6162,126 @@ targets: deps: - grpc uses_polling: false +- name: core_end2end_tests + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + - test/core/end2end/end2end_tests.h + - test/core/end2end/fixtures/h2_oauth2_common.h + - test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h + - test/core/end2end/fixtures/h2_ssl_tls_common.h + - test/core/end2end/fixtures/h2_tls_common.h + - test/core/end2end/fixtures/http_proxy_fixture.h + - test/core/end2end/fixtures/inproc_fixture.h + - test/core/end2end/fixtures/local_util.h + - test/core/end2end/fixtures/proxy.h + - test/core/end2end/fixtures/secure_fixture.h + - test/core/end2end/fixtures/sockpair_fixture.h + - test/core/end2end/tests/cancel_test_helpers.h + - test/core/util/test_lb_policies.h + src: + - test/core/end2end/cq_verifier.cc + - test/core/end2end/end2end_test_main.cc + - test/core/end2end/end2end_tests.cc + - test/core/end2end/fixtures/http_proxy_fixture.cc + - test/core/end2end/fixtures/local_util.cc + - test/core/end2end/fixtures/proxy.cc + - test/core/end2end/tests/bad_ping.cc + - test/core/end2end/tests/binary_metadata.cc + - test/core/end2end/tests/call_creds.cc + - test/core/end2end/tests/call_host_override.cc + - test/core/end2end/tests/cancel_after_accept.cc + - test/core/end2end/tests/cancel_after_client_done.cc + - test/core/end2end/tests/cancel_after_invoke.cc + - test/core/end2end/tests/cancel_after_round_trip.cc + - test/core/end2end/tests/cancel_before_invoke.cc + - test/core/end2end/tests/cancel_in_a_vacuum.cc + - test/core/end2end/tests/cancel_with_status.cc + - test/core/end2end/tests/channelz.cc + - test/core/end2end/tests/client_streaming.cc + - test/core/end2end/tests/compressed_payload.cc + - test/core/end2end/tests/connectivity.cc + - test/core/end2end/tests/default_host.cc + - test/core/end2end/tests/disappearing_server.cc + - test/core/end2end/tests/empty_batch.cc + - test/core/end2end/tests/filter_causes_close.cc + - test/core/end2end/tests/filter_context.cc + - test/core/end2end/tests/filter_init_fails.cc + - test/core/end2end/tests/filtered_metadata.cc + - test/core/end2end/tests/graceful_server_shutdown.cc + - test/core/end2end/tests/grpc_authz.cc + - test/core/end2end/tests/high_initial_seqno.cc + - test/core/end2end/tests/hpack_size.cc + - test/core/end2end/tests/invoke_large_request.cc + - test/core/end2end/tests/keepalive_timeout.cc + - test/core/end2end/tests/large_metadata.cc + - test/core/end2end/tests/max_concurrent_streams.cc + - test/core/end2end/tests/max_connection_age.cc + - test/core/end2end/tests/max_connection_idle.cc + - test/core/end2end/tests/max_message_length.cc + - test/core/end2end/tests/negative_deadline.cc + - test/core/end2end/tests/no_logging.cc + - test/core/end2end/tests/no_op.cc + - test/core/end2end/tests/payload.cc + - test/core/end2end/tests/ping.cc + - test/core/end2end/tests/ping_pong_streaming.cc + - test/core/end2end/tests/proxy_auth.cc + - test/core/end2end/tests/registered_call.cc + - test/core/end2end/tests/request_with_flags.cc + - test/core/end2end/tests/request_with_payload.cc + - test/core/end2end/tests/resource_quota_server.cc + - test/core/end2end/tests/retry.cc + - test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc + - test/core/end2end/tests/retry_cancel_during_delay.cc + - test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc + - test/core/end2end/tests/retry_cancellation.cc + - test/core/end2end/tests/retry_disabled.cc + - test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc + - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc + - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + - test/core/end2end/tests/retry_lb_drop.cc + - test/core/end2end/tests/retry_lb_fail.cc + - test/core/end2end/tests/retry_non_retriable_status.cc + - test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc + - test/core/end2end/tests/retry_per_attempt_recv_timeout.cc + - test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc + - test/core/end2end/tests/retry_recv_initial_metadata.cc + - test/core/end2end/tests/retry_recv_message.cc + - test/core/end2end/tests/retry_recv_message_replay.cc + - test/core/end2end/tests/retry_recv_trailing_metadata_error.cc + - test/core/end2end/tests/retry_send_initial_metadata_refs.cc + - test/core/end2end/tests/retry_send_op_fails.cc + - test/core/end2end/tests/retry_send_recv_batch.cc + - test/core/end2end/tests/retry_server_pushback_delay.cc + - test/core/end2end/tests/retry_server_pushback_disabled.cc + - test/core/end2end/tests/retry_streaming.cc + - test/core/end2end/tests/retry_streaming_after_commit.cc + - test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc + - test/core/end2end/tests/retry_throttled.cc + - test/core/end2end/tests/retry_too_many_attempts.cc + - test/core/end2end/tests/retry_transparent_goaway.cc + - test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc + - test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc + - test/core/end2end/tests/retry_unref_before_finish.cc + - test/core/end2end/tests/retry_unref_before_recv.cc + - test/core/end2end/tests/server_finishes_request.cc + - test/core/end2end/tests/server_streaming.cc + - test/core/end2end/tests/shutdown_finishes_calls.cc + - test/core/end2end/tests/shutdown_finishes_tags.cc + - test/core/end2end/tests/simple_delayed_request.cc + - test/core/end2end/tests/simple_metadata.cc + - test/core/end2end/tests/simple_request.cc + - test/core/end2end/tests/streaming_error_response.cc + - test/core/end2end/tests/trailing_metadata.cc + - test/core/end2end/tests/write_buffering.cc + - test/core/end2end/tests/write_buffering_at_end.cc + - test/core/util/test_lb_policies.cc + deps: + - grpc_authorization_provider + - grpc_unsecure + - grpc_test_util - name: cpp_impl_of_test gtest: true build: test @@ -6425,6 +6377,21 @@ targets: - test/core/gprpp/dual_ref_counted_test.cc deps: - grpc_test_util +- name: dualstack_socket_test + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + src: + - test/core/end2end/cq_verifier.cc + - test/core/end2end/dualstack_socket_test.cc + deps: + - grpc_test_util + platforms: + - linux + - posix + - mac - name: duplicate_header_bad_client_test gtest: true build: test @@ -7968,6 +7935,17 @@ targets: - test/cpp/end2end/generic_end2end_test.cc deps: - grpc++_test_util +- name: goaway_server_test + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + src: + - test/core/end2end/cq_verifier.cc + - test/core/end2end/goaway_server_test.cc + deps: + - grpc_test_util - name: google_c2p_resolver_test gtest: true build: test @@ -8505,12 +8483,14 @@ targets: - test/core/end2end/fixtures/local_util.h - test/core/end2end/fixtures/secure_fixture.h - test/core/end2end/fixtures/sockpair_fixture.h + - test/core/end2end/tests/cancel_test_helpers.h src: - test/core/end2end/cq_verifier.cc - test/core/end2end/data/client_certs.cc - test/core/end2end/data/server1_cert.cc - test/core/end2end/data/server1_key.cc - test/core/end2end/data/test_root_cert.cc + - test/core/end2end/end2end_tests.cc - test/core/end2end/fixtures/local_util.cc - test/core/end2end/h2_ssl_cert_test.cc deps: @@ -9043,6 +9023,17 @@ targets: deps: - grpc++_test_config - grpc++_test_util +- name: invalid_call_argument_test + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + src: + - test/core/end2end/cq_verifier.cc + - test/core/end2end/invalid_call_argument_test.cc + deps: + - grpc_test_util - name: iocp_test gtest: true build: test @@ -9676,6 +9667,17 @@ targets: - test/core/gprpp/no_destruct_test.cc deps: [] uses_polling: false +- name: no_server_test + gtest: true + build: test + language: c++ + headers: + - test/core/end2end/cq_verifier.h + src: + - test/core/end2end/cq_verifier.cc + - test/core/end2end/no_server_test.cc + deps: + - grpc_test_util - name: nonblocking_test gtest: true build: test diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index df22e350a6e..c071ff7c43b 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -2799,159 +2799,6 @@ Pod::Spec.new do |s| 'third_party/objective_c/Cronet/bidirectional_stream_c.h' end - s.subspec 'Tests' do |ss| - ss.header_mappings_dir = '.' - - ss.dependency "#{s.name}/Interface", version - ss.dependency "#{s.name}/Implementation", version - ss.dependency 'abseil/debugging/failure_signal_handler', abseil_version - ss.dependency 'abseil/debugging/stacktrace', abseil_version - ss.dependency 'abseil/debugging/symbolize', abseil_version - - ss.source_files = 'src/core/lib/security/authorization/grpc_authorization_policy_provider.cc', - 'src/core/lib/security/authorization/grpc_authorization_policy_provider.h', - 'src/core/lib/security/authorization/rbac_translator.cc', - 'src/core/lib/security/authorization/rbac_translator.h', - 'test/core/end2end/cq_verifier.cc', - 'test/core/end2end/cq_verifier.h', - 'test/core/end2end/data/client_certs.cc', - 'test/core/end2end/data/server1_cert.cc', - 'test/core/end2end/data/server1_key.cc', - 'test/core/end2end/data/ssl_test_data.h', - 'test/core/end2end/data/test_root_cert.cc', - 'test/core/end2end/end2end_test_utils.cc', - 'test/core/end2end/end2end_tests.cc', - 'test/core/end2end/end2end_tests.h', - 'test/core/end2end/fixtures/h2_oauth2_common.h', - 'test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h', - 'test/core/end2end/fixtures/h2_ssl_tls_common.h', - 'test/core/end2end/fixtures/h2_tls_common.h', - 'test/core/end2end/fixtures/http_proxy_fixture.cc', - 'test/core/end2end/fixtures/http_proxy_fixture.h', - 'test/core/end2end/fixtures/inproc_fixture.h', - 'test/core/end2end/fixtures/local_util.cc', - 'test/core/end2end/fixtures/local_util.h', - 'test/core/end2end/fixtures/proxy.cc', - 'test/core/end2end/fixtures/proxy.h', - 'test/core/end2end/fixtures/secure_fixture.h', - 'test/core/end2end/fixtures/sockpair_fixture.h', - 'test/core/end2end/tests/authority_not_supported.cc', - 'test/core/end2end/tests/bad_hostname.cc', - 'test/core/end2end/tests/bad_ping.cc', - 'test/core/end2end/tests/binary_metadata.cc', - 'test/core/end2end/tests/call_creds.cc', - 'test/core/end2end/tests/call_host_override.cc', - 'test/core/end2end/tests/cancel_after_accept.cc', - 'test/core/end2end/tests/cancel_after_client_done.cc', - 'test/core/end2end/tests/cancel_after_invoke.cc', - 'test/core/end2end/tests/cancel_after_round_trip.cc', - 'test/core/end2end/tests/cancel_before_invoke.cc', - 'test/core/end2end/tests/cancel_in_a_vacuum.cc', - 'test/core/end2end/tests/cancel_test_helpers.h', - 'test/core/end2end/tests/cancel_with_status.cc', - 'test/core/end2end/tests/channelz.cc', - 'test/core/end2end/tests/client_streaming.cc', - 'test/core/end2end/tests/compressed_payload.cc', - 'test/core/end2end/tests/connectivity.cc', - 'test/core/end2end/tests/default_host.cc', - 'test/core/end2end/tests/disappearing_server.cc', - 'test/core/end2end/tests/empty_batch.cc', - 'test/core/end2end/tests/filter_causes_close.cc', - 'test/core/end2end/tests/filter_context.cc', - 'test/core/end2end/tests/filter_init_fails.cc', - 'test/core/end2end/tests/filter_latency.cc', - 'test/core/end2end/tests/filter_status_code.cc', - 'test/core/end2end/tests/filtered_metadata.cc', - 'test/core/end2end/tests/graceful_server_shutdown.cc', - 'test/core/end2end/tests/grpc_authz.cc', - 'test/core/end2end/tests/high_initial_seqno.cc', - 'test/core/end2end/tests/hpack_size.cc', - 'test/core/end2end/tests/invoke_large_request.cc', - 'test/core/end2end/tests/keepalive_timeout.cc', - 'test/core/end2end/tests/large_metadata.cc', - 'test/core/end2end/tests/max_concurrent_streams.cc', - 'test/core/end2end/tests/max_connection_age.cc', - 'test/core/end2end/tests/max_connection_idle.cc', - 'test/core/end2end/tests/max_message_length.cc', - 'test/core/end2end/tests/negative_deadline.cc', - 'test/core/end2end/tests/no_logging.cc', - 'test/core/end2end/tests/no_op.cc', - 'test/core/end2end/tests/payload.cc', - 'test/core/end2end/tests/ping.cc', - 'test/core/end2end/tests/ping_pong_streaming.cc', - 'test/core/end2end/tests/proxy_auth.cc', - 'test/core/end2end/tests/registered_call.cc', - 'test/core/end2end/tests/request_with_flags.cc', - 'test/core/end2end/tests/request_with_payload.cc', - 'test/core/end2end/tests/resource_quota_server.cc', - 'test/core/end2end/tests/retry.cc', - 'test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc', - 'test/core/end2end/tests/retry_cancel_during_delay.cc', - 'test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc', - 'test/core/end2end/tests/retry_cancellation.cc', - 'test/core/end2end/tests/retry_disabled.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc', - 'test/core/end2end/tests/retry_lb_drop.cc', - 'test/core/end2end/tests/retry_lb_fail.cc', - 'test/core/end2end/tests/retry_non_retriable_status.cc', - 'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc', - 'test/core/end2end/tests/retry_per_attempt_recv_timeout.cc', - 'test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc', - 'test/core/end2end/tests/retry_recv_initial_metadata.cc', - 'test/core/end2end/tests/retry_recv_message.cc', - 'test/core/end2end/tests/retry_recv_message_replay.cc', - 'test/core/end2end/tests/retry_recv_trailing_metadata_error.cc', - 'test/core/end2end/tests/retry_send_initial_metadata_refs.cc', - 'test/core/end2end/tests/retry_send_op_fails.cc', - 'test/core/end2end/tests/retry_send_recv_batch.cc', - 'test/core/end2end/tests/retry_server_pushback_delay.cc', - 'test/core/end2end/tests/retry_server_pushback_disabled.cc', - 'test/core/end2end/tests/retry_streaming.cc', - 'test/core/end2end/tests/retry_streaming_after_commit.cc', - 'test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc', - 'test/core/end2end/tests/retry_throttled.cc', - 'test/core/end2end/tests/retry_too_many_attempts.cc', - 'test/core/end2end/tests/retry_transparent_goaway.cc', - 'test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc', - 'test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc', - 'test/core/end2end/tests/retry_unref_before_finish.cc', - 'test/core/end2end/tests/retry_unref_before_recv.cc', - 'test/core/end2end/tests/server_finishes_request.cc', - 'test/core/end2end/tests/server_streaming.cc', - 'test/core/end2end/tests/shutdown_finishes_calls.cc', - 'test/core/end2end/tests/shutdown_finishes_tags.cc', - 'test/core/end2end/tests/simple_delayed_request.cc', - 'test/core/end2end/tests/simple_metadata.cc', - 'test/core/end2end/tests/simple_request.cc', - 'test/core/end2end/tests/streaming_error_response.cc', - 'test/core/end2end/tests/trailing_metadata.cc', - 'test/core/end2end/tests/write_buffering.cc', - 'test/core/end2end/tests/write_buffering_at_end.cc', - 'test/core/event_engine/test_init.cc', - 'test/core/event_engine/test_init.h', - 'test/core/util/build.cc', - 'test/core/util/build.h', - 'test/core/util/port.cc', - 'test/core/util/port.h', - 'test/core/util/port_isolated_runtime_environment.cc', - 'test/core/util/port_server_client.cc', - 'test/core/util/port_server_client.h', - 'test/core/util/reconnect_server.cc', - 'test/core/util/reconnect_server.h', - 'test/core/util/stack_tracer.cc', - 'test/core/util/stack_tracer.h', - 'test/core/util/test_config.cc', - 'test/core/util/test_config.h', - 'test/core/util/test_lb_policies.cc', - 'test/core/util/test_lb_policies.h', - 'test/core/util/test_tcp_server.cc', - 'test/core/util/test_tcp_server.h', - 'test/core/util/tls_utils.cc', - 'test/core/util/tls_utils.h' - end - # patch include of openssl to openssl_grpc s.prepare_command = <<-END_OF_COMMAND set -e diff --git a/grpc.gyp b/grpc.gyp index e6410454c7b..d912b9ffd24 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -173,120 +173,6 @@ 'third_party/address_sorting/address_sorting_windows.c', ], }, - { - 'target_name': 'end2end_tests', - 'type': 'static_library', - 'dependencies': [ - 'grpc_authorization_provider', - 'grpc_test_util', - ], - 'sources': [ - 'test/core/end2end/cq_verifier.cc', - 'test/core/end2end/data/client_certs.cc', - 'test/core/end2end/data/server1_cert.cc', - 'test/core/end2end/data/server1_key.cc', - 'test/core/end2end/data/test_root_cert.cc', - 'test/core/end2end/end2end_test_utils.cc', - 'test/core/end2end/end2end_tests.cc', - 'test/core/end2end/fixtures/http_proxy_fixture.cc', - 'test/core/end2end/fixtures/local_util.cc', - 'test/core/end2end/fixtures/proxy.cc', - 'test/core/end2end/tests/authority_not_supported.cc', - 'test/core/end2end/tests/bad_hostname.cc', - 'test/core/end2end/tests/bad_ping.cc', - 'test/core/end2end/tests/binary_metadata.cc', - 'test/core/end2end/tests/call_creds.cc', - 'test/core/end2end/tests/call_host_override.cc', - 'test/core/end2end/tests/cancel_after_accept.cc', - 'test/core/end2end/tests/cancel_after_client_done.cc', - 'test/core/end2end/tests/cancel_after_invoke.cc', - 'test/core/end2end/tests/cancel_after_round_trip.cc', - 'test/core/end2end/tests/cancel_before_invoke.cc', - 'test/core/end2end/tests/cancel_in_a_vacuum.cc', - 'test/core/end2end/tests/cancel_with_status.cc', - 'test/core/end2end/tests/channelz.cc', - 'test/core/end2end/tests/client_streaming.cc', - 'test/core/end2end/tests/compressed_payload.cc', - 'test/core/end2end/tests/connectivity.cc', - 'test/core/end2end/tests/default_host.cc', - 'test/core/end2end/tests/disappearing_server.cc', - 'test/core/end2end/tests/empty_batch.cc', - 'test/core/end2end/tests/filter_causes_close.cc', - 'test/core/end2end/tests/filter_context.cc', - 'test/core/end2end/tests/filter_init_fails.cc', - 'test/core/end2end/tests/filter_latency.cc', - 'test/core/end2end/tests/filter_status_code.cc', - 'test/core/end2end/tests/filtered_metadata.cc', - 'test/core/end2end/tests/graceful_server_shutdown.cc', - 'test/core/end2end/tests/grpc_authz.cc', - 'test/core/end2end/tests/high_initial_seqno.cc', - 'test/core/end2end/tests/hpack_size.cc', - 'test/core/end2end/tests/invoke_large_request.cc', - 'test/core/end2end/tests/keepalive_timeout.cc', - 'test/core/end2end/tests/large_metadata.cc', - 'test/core/end2end/tests/max_concurrent_streams.cc', - 'test/core/end2end/tests/max_connection_age.cc', - 'test/core/end2end/tests/max_connection_idle.cc', - 'test/core/end2end/tests/max_message_length.cc', - 'test/core/end2end/tests/negative_deadline.cc', - 'test/core/end2end/tests/no_logging.cc', - 'test/core/end2end/tests/no_op.cc', - 'test/core/end2end/tests/payload.cc', - 'test/core/end2end/tests/ping.cc', - 'test/core/end2end/tests/ping_pong_streaming.cc', - 'test/core/end2end/tests/proxy_auth.cc', - 'test/core/end2end/tests/registered_call.cc', - 'test/core/end2end/tests/request_with_flags.cc', - 'test/core/end2end/tests/request_with_payload.cc', - 'test/core/end2end/tests/resource_quota_server.cc', - 'test/core/end2end/tests/retry.cc', - 'test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc', - 'test/core/end2end/tests/retry_cancel_during_delay.cc', - 'test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc', - 'test/core/end2end/tests/retry_cancellation.cc', - 'test/core/end2end/tests/retry_disabled.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc', - 'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc', - 'test/core/end2end/tests/retry_lb_drop.cc', - 'test/core/end2end/tests/retry_lb_fail.cc', - 'test/core/end2end/tests/retry_non_retriable_status.cc', - 'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc', - 'test/core/end2end/tests/retry_per_attempt_recv_timeout.cc', - 'test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc', - 'test/core/end2end/tests/retry_recv_initial_metadata.cc', - 'test/core/end2end/tests/retry_recv_message.cc', - 'test/core/end2end/tests/retry_recv_message_replay.cc', - 'test/core/end2end/tests/retry_recv_trailing_metadata_error.cc', - 'test/core/end2end/tests/retry_send_initial_metadata_refs.cc', - 'test/core/end2end/tests/retry_send_op_fails.cc', - 'test/core/end2end/tests/retry_send_recv_batch.cc', - 'test/core/end2end/tests/retry_server_pushback_delay.cc', - 'test/core/end2end/tests/retry_server_pushback_disabled.cc', - 'test/core/end2end/tests/retry_streaming.cc', - 'test/core/end2end/tests/retry_streaming_after_commit.cc', - 'test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc', - 'test/core/end2end/tests/retry_throttled.cc', - 'test/core/end2end/tests/retry_too_many_attempts.cc', - 'test/core/end2end/tests/retry_transparent_goaway.cc', - 'test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc', - 'test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc', - 'test/core/end2end/tests/retry_unref_before_finish.cc', - 'test/core/end2end/tests/retry_unref_before_recv.cc', - 'test/core/end2end/tests/server_finishes_request.cc', - 'test/core/end2end/tests/server_streaming.cc', - 'test/core/end2end/tests/shutdown_finishes_calls.cc', - 'test/core/end2end/tests/shutdown_finishes_tags.cc', - 'test/core/end2end/tests/simple_delayed_request.cc', - 'test/core/end2end/tests/simple_metadata.cc', - 'test/core/end2end/tests/simple_request.cc', - 'test/core/end2end/tests/streaming_error_response.cc', - 'test/core/end2end/tests/trailing_metadata.cc', - 'test/core/end2end/tests/write_buffering.cc', - 'test/core/end2end/tests/write_buffering_at_end.cc', - 'test/core/util/test_lb_policies.cc', - ], - }, { 'target_name': 'gpr', 'type': 'static_library', diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index ab0fcbba904..27e3342ecb2 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -369,6 +369,8 @@ static void read_channel_args(grpc_chttp2_transport* t, .GetObjectRef()); } + t->ack_pings = channel_args.GetBool("grpc.http2.ack_pings").value_or(true); + const int soft_limit = channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1); if (soft_limit < 0) { diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.cc b/src/core/ext/transport/chttp2/transport/frame_ping.cc index 897a8585bc5..f9f111a827e 100644 --- a/src/core/ext/transport/chttp2/transport/frame_ping.cc +++ b/src/core/ext/transport/chttp2/transport/frame_ping.cc @@ -35,8 +35,6 @@ #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/lib/gprpp/time.h" -static bool g_disable_ping_ack = false; - grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) { grpc_slice slice = GRPC_SLICE_MALLOC(9 + 8); uint8_t* p = GRPC_SLICE_START_PTR(slice); @@ -116,7 +114,7 @@ grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser, t->ping_recv_state.last_ping_recv_time = now; } - if (!g_disable_ping_ack) { + if (t->ack_pings) { if (t->ping_ack_count == t->ping_ack_capacity) { t->ping_ack_capacity = std::max(t->ping_ack_capacity * 3 / 2, size_t{3}); @@ -132,7 +130,3 @@ grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser, return absl::OkStatus(); } - -void grpc_set_disable_ping_ack(bool disable_ping_ack) { - g_disable_ping_ack = disable_ping_ack; -} diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h index b49e0eadada..6da1a3ad970 100644 --- a/src/core/ext/transport/chttp2/transport/frame_ping.h +++ b/src/core/ext/transport/chttp2/transport/frame_ping.h @@ -43,7 +43,4 @@ grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser, const grpc_slice& slice, int is_last); -// Test-only function for disabling ping ack -void grpc_set_disable_ping_ack(bool disable_ping_ack); - #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_PING_H diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc b/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc index 1e582e28bba..33f04a7487d 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc @@ -69,6 +69,7 @@ auto HPackTable::MementoRingBuffer::Lookup(uint32_t index) const void HPackTable::MementoRingBuffer::Rebuild(uint32_t max_entries) { if (max_entries == max_entries_) return; + max_entries_ = max_entries; std::vector entries; entries.reserve(num_entries_); for (size_t i = 0; i < num_entries_; i++) { diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index c25a520a5c1..921296198d0 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -436,6 +436,8 @@ struct grpc_chttp2_transport /// If start_bdp_ping_locked has been called bool bdp_ping_started = false; + // True if pings should be acked + bool ack_pings = true; // next bdp ping timer handle absl::optional next_bdp_ping_timer_handle; diff --git a/src/core/lib/debug/trace.cc b/src/core/lib/debug/trace.cc index 71d427dac6e..add527637bb 100644 --- a/src/core/lib/debug/trace.cc +++ b/src/core/lib/debug/trace.cc @@ -24,6 +24,7 @@ #include #include +#include #include "absl/strings/string_view.h" @@ -77,12 +78,17 @@ void TraceFlagList::Add(TraceFlag* flag) { void TraceFlagList::LogAllTracers() { gpr_log(GPR_DEBUG, "available tracers:"); - TraceFlag* t; - for (t = root_tracer_; t != nullptr; t = t->next_tracer_) { + for (TraceFlag* t = root_tracer_; t != nullptr; t = t->next_tracer_) { gpr_log(GPR_DEBUG, "\t%s", t->name_); } } +void TraceFlagList::SaveTo(std::map& values) { + for (TraceFlag* t = root_tracer_; t != nullptr; t = t->next_tracer_) { + values[t->name_] = t->enabled(); + } +} + // Flags register themselves on the list during construction TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) { static_assert(std::is_trivially_destructible::value, @@ -91,6 +97,14 @@ TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) { TraceFlagList::Add(this); } +SavedTraceFlags::SavedTraceFlags() { TraceFlagList::SaveTo(values_); } + +void SavedTraceFlags::Restore() { + for (const auto& flag : values_) { + TraceFlagList::Set(flag.first.c_str(), flag.second); + } +} + } // namespace grpc_core static void add(const char* beg, const char* end, char*** ss, size_t* ns) { @@ -138,11 +152,6 @@ static void parse(const char* s) { gpr_free(strings); } -void grpc_tracer_init(const char* env_var_name) { - (void)env_var_name; // suppress unused variable error - grpc_tracer_init(); -} - void grpc_tracer_init() { parse(std::string(grpc_core::ConfigVars::Get().Trace()).c_str()); } diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h index 9e7071075f9..992cc92fc57 100644 --- a/src/core/lib/debug/trace.h +++ b/src/core/lib/debug/trace.h @@ -22,10 +22,8 @@ #include #include - -// TODO(veblush): Remove this deprecated function once codes depending on this -// function are updated in the internal repo. -void grpc_tracer_init(const char* env_var_name); +#include +#include void grpc_tracer_init(); void grpc_tracer_shutdown(void); @@ -37,6 +35,7 @@ class TraceFlagList { public: static bool Set(const char* name, bool enabled); static void Add(TraceFlag* flag); + static void SaveTo(std::map& values); private: static void LogAllTracers(); @@ -101,6 +100,15 @@ class DebugOnlyTraceFlag { }; #endif +class SavedTraceFlags { + public: + SavedTraceFlags(); + void Restore(); + + private: + std::map values_; +}; + } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_DEBUG_TRACE_H diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index 3282fe17d08..bed5ccccfe8 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -338,7 +338,7 @@ static void timer_init(grpc_timer* timer, grpc_core::Timestamp deadline, #endif if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { - gpr_log(GPR_INFO, "TIMER %p: SET %" PRId64 " now %" PRId64 " call %p[%p]", + gpr_log(GPR_DEBUG, "TIMER %p: SET %" PRId64 " now %" PRId64 " call %p[%p]", timer, deadline.milliseconds_after_process_epoch(), grpc_core::Timestamp::Now().milliseconds_after_process_epoch(), closure, closure->cb); @@ -374,7 +374,7 @@ static void timer_init(grpc_timer* timer, grpc_core::Timestamp deadline, list_join(&shard->list, timer); } if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { - gpr_log(GPR_INFO, + gpr_log(GPR_DEBUG, " .. add to shard %d with queue_deadline_cap=%" PRId64 " => is_first_timer=%s", static_cast(shard - g_shards), @@ -397,7 +397,7 @@ static void timer_init(grpc_timer* timer, grpc_core::Timestamp deadline, if (is_first_timer) { gpr_mu_lock(&g_shared_mutables.mu); if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { - gpr_log(GPR_INFO, " .. old shard min_deadline=%" PRId64, + gpr_log(GPR_DEBUG, " .. old shard min_deadline=%" PRId64, shard->min_deadline.milliseconds_after_process_epoch()); } if (deadline < shard->min_deadline) { @@ -439,7 +439,7 @@ static void timer_cancel(grpc_timer* timer) { timer_shard* shard = &g_shards[grpc_core::HashPointer(timer, g_num_shards)]; gpr_mu_lock(&shard->mu); if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { - gpr_log(GPR_INFO, "TIMER %p: CANCEL pending=%s", timer, + gpr_log(GPR_DEBUG, "TIMER %p: CANCEL pending=%s", timer, timer->pending ? "true" : "false"); } @@ -480,7 +480,7 @@ static bool refill_heap(timer_shard* shard, grpc_core::Timestamp now) { grpc_core::Duration::FromSecondsAsDouble(deadline_delta); if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, " .. shard[%d]->queue_deadline_cap --> %" PRId64, + gpr_log(GPR_DEBUG, " .. shard[%d]->queue_deadline_cap --> %" PRId64, static_cast(shard - g_shards), shard->queue_deadline_cap.milliseconds_after_process_epoch()); } @@ -492,7 +492,7 @@ static bool refill_heap(timer_shard* shard, grpc_core::Timestamp now) { if (timer_deadline < shard->queue_deadline_cap) { if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, " .. add timer with deadline %" PRId64 " to heap", + gpr_log(GPR_DEBUG, " .. add timer with deadline %" PRId64 " to heap", timer_deadline.milliseconds_after_process_epoch()); } list_remove(timer); @@ -509,7 +509,7 @@ static grpc_timer* pop_one(timer_shard* shard, grpc_core::Timestamp now) { grpc_timer* timer; for (;;) { if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, " .. shard[%d]: heap_empty=%s", + gpr_log(GPR_DEBUG, " .. shard[%d]: heap_empty=%s", static_cast(shard - g_shards), grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false"); } @@ -522,14 +522,14 @@ static grpc_timer* pop_one(timer_shard* shard, grpc_core::Timestamp now) { grpc_core::Timestamp::FromMillisecondsAfterProcessEpoch( timer->deadline); if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, + gpr_log(GPR_DEBUG, " .. check top timer deadline=%" PRId64 " now=%" PRId64, timer_deadline.milliseconds_after_process_epoch(), now.milliseconds_after_process_epoch()); } if (timer_deadline > now) return nullptr; if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { - gpr_log(GPR_INFO, "TIMER %p: FIRE %" PRId64 "ms late", timer, + gpr_log(GPR_DEBUG, "TIMER %p: FIRE %" PRId64 "ms late", timer, (now - timer_deadline).millis()); } timer->pending = false; @@ -553,7 +553,7 @@ static size_t pop_timers(timer_shard* shard, grpc_core::Timestamp now, *new_min_deadline = compute_min_deadline(shard); gpr_mu_unlock(&shard->mu); if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, " .. shard[%d] popped %" PRIdPTR, + gpr_log(GPR_DEBUG, " .. shard[%d] popped %" PRIdPTR, static_cast(shard - g_shards), n); } return n; @@ -593,7 +593,7 @@ static grpc_timer_check_result run_some_expired_timers( if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { gpr_log( - GPR_INFO, " .. shard[%d]->min_deadline = %" PRId64, + GPR_DEBUG, " .. shard[%d]->min_deadline = %" PRId64, static_cast(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline.milliseconds_after_process_epoch()); } @@ -612,7 +612,7 @@ static grpc_timer_check_result run_some_expired_timers( if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { gpr_log( - GPR_INFO, + GPR_DEBUG, " .. result --> %d" ", shard[%d]->min_deadline %" PRId64 " --> %" PRId64 ", now=%" PRId64, @@ -671,7 +671,7 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) { *next = std::min(*next, min_timer); } if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { - gpr_log(GPR_INFO, "TIMER CHECK SKIP: now=%" PRId64 " min_timer=%" PRId64, + gpr_log(GPR_DEBUG, "TIMER CHECK SKIP: now=%" PRId64 " min_timer=%" PRId64, now.milliseconds_after_process_epoch(), min_timer.milliseconds_after_process_epoch()); } @@ -693,7 +693,7 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) { } #if GPR_ARCH_64 gpr_log( - GPR_INFO, + GPR_DEBUG, "TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64 " glob_min=%" PRId64, now.milliseconds_after_process_epoch(), next_str.c_str(), @@ -702,7 +702,8 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) { gpr_atm_no_barrier_load((gpr_atm*)(&g_shared_mutables.min_timer))) .milliseconds_after_process_epoch()); #else - gpr_log(GPR_INFO, "TIMER CHECK BEGIN: now=%" PRId64 " next=%s min=%" PRId64, + gpr_log(GPR_DEBUG, + "TIMER CHECK BEGIN: now=%" PRId64 " next=%s min=%" PRId64, now.milliseconds_after_process_epoch(), next_str.c_str(), min_timer.milliseconds_after_process_epoch()); #endif @@ -718,7 +719,7 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) { } else { next_str = absl::StrCat(next->milliseconds_after_process_epoch()); } - gpr_log(GPR_INFO, "TIMER CHECK END: r=%d; next=%s", r, next_str.c_str()); + gpr_log(GPR_DEBUG, "TIMER CHECK END: r=%d; next=%s", r, next_str.c_str()); } return r; } diff --git a/src/core/lib/slice/slice.h b/src/core/lib/slice/slice.h index 2640ee80644..ecbdae683f7 100644 --- a/src/core/lib/slice/slice.h +++ b/src/core/lib/slice/slice.h @@ -298,6 +298,8 @@ class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND MutableSlice // Array access uint8_t& operator[](size_t i) { return mutable_data()[i]; } + + using slice_detail::BaseSlice::c_slice_ptr; }; class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND Slice diff --git a/src/objective-c/tests/BUILD b/src/objective-c/tests/BUILD index fd4b9c8fede..efb3ba8d223 100644 --- a/src/objective-c/tests/BUILD +++ b/src/objective-c/tests/BUILD @@ -22,7 +22,6 @@ load( "local_objc_grpc_library", "proto_library_objc_wrapper", ) -load("//test/core/end2end:generate_tests.bzl", "grpc_end2end_tests") load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle") load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test") load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application", "tvos_unit_test") @@ -33,8 +32,6 @@ package(default_visibility = ["//visibility:public"]) exports_files(["LICENSE"]) -grpc_end2end_tests() - proto_library_objc_wrapper( name = "messages_proto", srcs = ["RemoteTestClient/messages.proto"], @@ -188,7 +185,8 @@ grpc_objc_testing_library( deps = [ "InteropTests-lib", "//src/objective-c:grpc_objc_client_core_cronet_testing", - "//test/core/end2end:end2end_tests", + "//test/core/end2end:cq_verifier", + "//test/core/end2end:ssl_test_data", "//third_party/objective_c/Cronet:cronet_c_for_grpc", ], ) @@ -206,7 +204,7 @@ grpc_objc_testing_library( "//:grpc++_cronet_credentials", "//src/objective-c:grpc_objc_client_core_cronet_testing", "//src/proto/grpc/testing:echo_proto", - "//test/core/end2end:end2end_tests", + "//test/core/end2end:ssl_test_data", ], ) diff --git a/src/objective-c/tests/CronetTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CronetTests/CoreCronetEnd2EndTests.mm deleted file mode 100644 index 02ea853b2bd..00000000000 --- a/src/objective-c/tests/CronetTests/CoreCronetEnd2EndTests.mm +++ /dev/null @@ -1,330 +0,0 @@ -/* - * - * Copyright 2015 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. - * - */ - -/* - * This test file is derived from fixture h2_ssl.c in core end2end test - * (test/core/end2end/fixture/h2_ssl.c). The structure of the fixture is - * preserved as much as possible - * - * This fixture creates a server full stack using chttp2 and a client - * full stack using Cronet. End-to-end tests are run against this - * configuration - * - */ - -#import -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include "src/core/lib/gprpp/crash.h" - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "src/core/lib/gpr/string.h" -#include "src/core/lib/gpr/tmpfile.h" -#include "src/core/lib/gprpp/host_port.h" -#include "src/core/lib/security/credentials/credentials.h" - -#include "test/core/end2end/data/ssl_test_data.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -#import -#include - -#import "../ConfigureCronet.h" - -static void process_auth_failure(void *state, grpc_auth_context *ctx, const grpc_metadata *md, - size_t md_count, grpc_process_auth_metadata_done_cb cb, - void *user_data) { - GPR_ASSERT(state == nullptr); - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); -} - -class CronetFixture final : public SecureFixture { - private: - grpc_channel_credentials *MakeClientCreds(const grpc_core::ChannelArgs &args) override { - grpc_core::Crash("unreachable"); - } - grpc_server_credentials *MakeServerCreds(const grpc_core::ChannelArgs &args) override { - grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(nullptr, &pem_cert_key_pair, 1, 0, nullptr); - if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { - grpc_auth_metadata_processor processor = {process_auth_failure, nullptr, nullptr}; - grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); - } - return ssl_creds; - } - grpc_channel *MakeClient(const grpc_core::ChannelArgs &args) override { - stream_engine *cronetEngine = [Cronet getGlobalEngine]; - return grpc_cronet_secure_channel_create(cronetEngine, localaddr().c_str(), args.ToC().get(), - nullptr); - } -}; - -/* All test configurations */ - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, nullptr, - [](const grpc_core::ChannelArgs & /*client_args*/, - const grpc_core::ChannelArgs & /*server_args*/) { - return std::make_unique(); - }}, -}; - -static char *roots_filename; - -@interface CoreCronetEnd2EndTests : XCTestCase - -@end - -@implementation CoreCronetEnd2EndTests - -// The setUp() function is run before the test cases run and only run once -+ (void)setUp { - [super setUp]; - - FILE *roots_file; - size_t roots_size = strlen(test_root_cert); - - char *argv[] = {(char *)"CoreCronetEnd2EndTests"}; - int argc = 1; - grpc_test_init(&argc, argv); - grpc_end2end_tests_pre_init(); - - /* Set the SSL roots env var. */ - roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); - GPR_ASSERT(roots_filename != nullptr); - GPR_ASSERT(roots_file != nullptr); - GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); - fclose(roots_file); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = roots_filename; - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - configureCronet(/*enable_netlog=*/false); -} - -// The tearDown() function is run after all test cases finish running -+ (void)tearDown { - grpc_shutdown(); - - /* Cleanup. */ - remove(roots_filename); - gpr_free(roots_filename); - - [super tearDown]; -} - -- (void)testIndividualCase:(char *)test_case { - char *argv[] = {(char *)"h2_ssl", test_case}; - for (int i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(2, argv, configs[i]); - } -} - -// TODO(mxyan): Use NSStringFromSelector(_cmd) to acquire test name from the -// test case method name, so that bodies of test cases can stay identical -- (void)testAuthorityNotSupported { - [self testIndividualCase:(char *)"authority_not_supported"]; -} - -- (void)testBadHostname { - [self testIndividualCase:(char *)"bad_hostname"]; -} - -- (void)testBinaryMetadata { - [self testIndividualCase:(char *)"binary_metadata"]; -} - -- (void)testCallCreds { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"call_creds"]; -} - -- (void)testCancelAfterAccept { - [self testIndividualCase:(char *)"cancel_after_accept"]; -} - -- (void)testCancelAfterClientDone { - [self testIndividualCase:(char *)"cancel_after_client_done"]; -} - -- (void)testCancelAfterInvoke { - [self testIndividualCase:(char *)"cancel_after_invoke"]; -} - -- (void)testCancelAfterRoundTrip { - [self testIndividualCase:(char *)"cancel_after_round_trip"]; -} - -- (void)testCancelBeforeInvoke { - [self testIndividualCase:(char *)"cancel_before_invoke"]; -} - -- (void)testCancelInAVacuum { - [self testIndividualCase:(char *)"cancel_in_a_vacuum"]; -} - -- (void)testCancelWithStatus { - [self testIndividualCase:(char *)"cancel_with_status"]; -} - -- (void)testCompressedPayload { - [self testIndividualCase:(char *)"compressed_payload"]; -} - -- (void)testConnectivity { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"connectivity"]; -} - -- (void)testDefaultHost { - [self testIndividualCase:(char *)"default_host"]; -} - -- (void)testDisappearingServer { - [self testIndividualCase:(char *)"disappearing_server"]; -} - -- (void)testEmptyBatch { - [self testIndividualCase:(char *)"empty_batch"]; -} - -- (void)testFilterCausesClose { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"filter_causes_close"]; -} - -- (void)testGracefulServerShutdown { - [self testIndividualCase:(char *)"graceful_server_shutdown"]; -} - -- (void)testHighInitialSeqno { - [self testIndividualCase:(char *)"high_initial_seqno"]; -} - -- (void)testHpackSize { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"hpack_size"]; -} - -- (void)testIdempotentRequest { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"idempotent_request"]; -} - -- (void)testInvokeLargeRequest { - // NOT SUPPORTED (frame size) - // [self testIndividualCase:(char *)"invoke_large_request"]; -} - -- (void)testLargeMetadata { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"large_metadata"]; -} - -- (void)testMaxConcurrentStreams { - [self testIndividualCase:(char *)"max_concurrent_streams"]; -} - -- (void)testMaxMessageLength { - // NOT SUPPORTED (close_error) - // [self testIndividualCase:(char *)"max_message_length"]; -} - -- (void)testNegativeDeadline { - [self testIndividualCase:(char *)"negative_deadline"]; -} - -- (void)testNoOp { - [self testIndividualCase:(char *)"no_op"]; -} - -- (void)testPayload { - [self testIndividualCase:(char *)"payload"]; -} - -- (void)testPing { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"ping"]; -} - -- (void)testPingPongStreaming { - [self testIndividualCase:(char *)"ping_pong_streaming"]; -} - -- (void)testRegisteredCall { - [self testIndividualCase:(char *)"registered_call"]; -} - -- (void)testRequestWithFlags { - // NOT SUPPORTED - // [self testIndividualCase:(char *)"request_with_flags"]; -} - -- (void)testRequestWithPayload { - [self testIndividualCase:(char *)"request_with_payload"]; -} - -- (void)testServerFinishesRequest { - [self testIndividualCase:(char *)"server_finishes_request"]; -} - -- (void)testServerStreaming { - [self testIndividualCase:(char *)"server_streaming"]; -} - -- (void)testShutdownFinishesCalls { - [self testIndividualCase:(char *)"shutdown_finishes_calls"]; -} - -- (void)testShutdownFinishesTags { - [self testIndividualCase:(char *)"shutdown_finishes_tags"]; -} - -- (void)testSimpleDelayedRequest { - [self testIndividualCase:(char *)"simple_delayed_request"]; -} - -- (void)testSimpleMetadata { - [self testIndividualCase:(char *)"simple_metadata"]; -} - -- (void)testSimpleRequest { - [self testIndividualCase:(char *)"simple_request"]; -} - -- (void)testStreamingErrorResponse { - [self testIndividualCase:(char *)"streaming_error_response"]; -} - -- (void)testTrailingMetadata { - [self testIndividualCase:(char *)"trailing_metadata"]; -} - -@end diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 0604af70228..f3a8608e0a2 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -47,7 +47,6 @@ target 'CronetTests' do pod 'gRPC/GRPCCoreCronet', :path => GRPC_LOCAL_SRC pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" - pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true end target 'PerfTests' do diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index f9c099bb740..6eb7d4431fe 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -76,7 +76,6 @@ set(address_sorting_unwanted_files)) | set(list_lib_files("re2", ("headers", ))))) grpc_abseil_specs = list_abseil_specs("grpc") - grpc_tests_abseil_specs = list(sorted(set(list_abseil_specs("end2end_tests")) - set(grpc_abseil_specs))) # TODO(jtattermusch): build.yaml is now generated from bazel build # which doesn't have an explicit "grpc_cronet" target. Until it exists @@ -95,15 +94,6 @@ grpc_cronet_files = list(sorted(grpc_cronet_extra_impl_files)) grpc_cronet_public_headers = list(sorted(grpc_cronet_extra_public_headers)) - - grpc_test_util_files = list(sorted( - set(list_lib_files("end2end_tests", ("src", "headers"))) - - set(grpc_private_files) - - set(address_sorting_unwanted_files) - - set([ - # Subprocess is not supported in tvOS and not needed by our tests. - "test/core/util/subprocess_posix.cc", - ]))) %> Pod::Spec.new do |s| s.name = 'gRPC-Core' @@ -228,18 +218,6 @@ ss.source_files = ${ruby_multiline_list(grpc_cronet_files, 22)} end - s.subspec 'Tests' do |ss| - ss.header_mappings_dir = '.' - - ss.dependency "#{s.name}/Interface", version - ss.dependency "#{s.name}/Implementation", version - % for abseil_spec in grpc_tests_abseil_specs: - ss.dependency '${abseil_spec}', abseil_version - % endfor - - ss.source_files = ${ruby_multiline_list(grpc_test_util_files, 22)} - end - # patch include of openssl to openssl_grpc s.prepare_command = <<-END_OF_COMMAND set -e diff --git a/templates/test/core/end2end/end2end_defs.include b/templates/test/core/end2end/end2end_defs.include deleted file mode 100644 index 81ea76c41a0..00000000000 --- a/templates/test/core/end2end/end2end_defs.include +++ /dev/null @@ -1,72 +0,0 @@ -<%def name="end2end_selector(tests)"> -// -// -// Copyright 2015 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. -// -// - -<% tests = sorted(tests) %>\ -// This file is auto-generated - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include "absl/strings/str_format.h" - -#include - -#include "src/core/lib/gprpp/crash.h" - -static bool g_pre_init_called = false; - -% for test in tests: -extern void ${test}(const CoreTestConfiguration& config); -extern void ${test}_pre_init(void); -% endfor - -void grpc_end2end_tests_pre_init(void) { - GPR_ASSERT(!g_pre_init_called); - g_pre_init_called = true; -% for test in tests: - ${test}_pre_init(); -% endfor -} - -// NOLINTNEXTLINE(readability-function-size) -void grpc_end2end_tests(int argc, char **argv, - const CoreTestConfiguration& config) { - int i; - - GPR_ASSERT(g_pre_init_called); - - if (argc <= 1) { -% for test in tests: - ${test}(config); -% endfor - return; - } - - for (i = 1; i < argc; i++) { -% for test in tests: - if (0 == strcmp("${test}", argv[i])) { - ${test}(config); - continue; - } -% endfor - grpc_core::Crash(absl::StrFormat( "not a test: '%s'", argv[i])); - } -} diff --git a/templates/test/core/end2end/end2end_tests.cc.template b/templates/test/core/end2end/end2end_tests.cc.template deleted file mode 100644 index e6a49f2795a..00000000000 --- a/templates/test/core/end2end/end2end_tests.cc.template +++ /dev/null @@ -1,4 +0,0 @@ -%YAML 1.2 ---- | - <%namespace file="end2end_defs.include" import="*"/>\ - ${end2end_selector(core_end2end_tests.keys())} diff --git a/test/core/bad_client/generate_tests.bzl b/test/core/bad_client/generate_tests.bzl index 7ace2600810..b6acd9e5f51 100755 --- a/test/core/bad_client/generate_tests.bzl +++ b/test/core/bad_client/generate_tests.bzl @@ -43,6 +43,7 @@ def grpc_bad_client_tests(): srcs = ["bad_client.cc"], hdrs = ["bad_client.h"], language = "C++", + testonly = 1, deps = [ "//test/core/util:grpc_test_util", "//:grpc", diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD index 3438295a4df..e96aaceca35 100644 --- a/test/core/end2end/BUILD +++ b/test/core/end2end/BUILD @@ -13,7 +13,6 @@ # limitations under the License. load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") -load(":generate_tests.bzl", "grpc_end2end_tests") licenses(["notice"]) @@ -21,15 +20,18 @@ grpc_package(name = "test/core/end2end") grpc_cc_library( name = "cq_verifier", + testonly = 1, srcs = ["cq_verifier.cc"], hdrs = ["cq_verifier.h"], external_deps = [ + "absl/functional:any_invocable", "absl/strings", "absl/strings:str_format", "absl/types:variant", + "gtest", ], language = "C++", - visibility = ["//test:__subpackages__"], + visibility = ["//:__subpackages__"], deps = [ "//:debug_location", "//:gpr", @@ -50,7 +52,7 @@ grpc_cc_library( ], hdrs = ["data/ssl_test_data.h"], language = "C++", - visibility = ["//test:__subpackages__"], + visibility = ["//:__subpackages__"], ) grpc_cc_library( @@ -99,11 +101,44 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "end2end_test_lib", + testonly = 1, + srcs = [ + "end2end_tests.cc", + ], + hdrs = [ + "end2end_tests.h", + ], + external_deps = [ + "absl/memory", + "absl/random", + "absl/strings", + "absl/types:optional", + "absl/types:variant", + "gtest", + ], + deps = [ + "cq_verifier", + "//:config", + "//:debug_location", + "//:gpr", + "//:grpc", + "//:grpc_public_hdrs", + "//src/core:bitset", + "//src/core:channel_args", + "//src/core:no_destruct", + "//src/core:slice", + "//src/core:time", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_library( name = "fixture_support", + testonly = 1, srcs = ["fixtures/local_util.cc"], hdrs = [ - "end2end_tests.h", "fixtures/h2_oauth2_common.h", "fixtures/h2_ssl_cred_reload_fixture.h", "fixtures/h2_ssl_tls_common.h", @@ -112,14 +147,17 @@ grpc_cc_library( "fixtures/local_util.h", "fixtures/secure_fixture.h", "fixtures/sockpair_fixture.h", + "tests/cancel_test_helpers.h", ], external_deps = [ "absl/status", "absl/status:statusor", "absl/strings", + "gtest", ], language = "C++", deps = [ + "end2end_test_lib", "//:config", "//:exec_ctx", "//:gpr", @@ -141,6 +179,162 @@ grpc_cc_library( ], ) +grpc_cc_test( + name = "core_end2end_tests", + timeout = "long", + srcs = [ + "end2end_test_main.cc", + "tests/bad_ping.cc", + "tests/binary_metadata.cc", + "tests/call_creds.cc", + "tests/call_host_override.cc", + "tests/cancel_after_accept.cc", + "tests/cancel_after_client_done.cc", + "tests/cancel_after_invoke.cc", + "tests/cancel_after_round_trip.cc", + "tests/cancel_before_invoke.cc", + "tests/cancel_in_a_vacuum.cc", + "tests/cancel_with_status.cc", + "tests/channelz.cc", + "tests/client_streaming.cc", + "tests/compressed_payload.cc", + "tests/connectivity.cc", + "tests/default_host.cc", + "tests/disappearing_server.cc", + "tests/empty_batch.cc", + "tests/filter_causes_close.cc", + "tests/filter_context.cc", + "tests/filter_init_fails.cc", + "tests/filtered_metadata.cc", + "tests/graceful_server_shutdown.cc", + "tests/grpc_authz.cc", + "tests/high_initial_seqno.cc", + "tests/hpack_size.cc", + "tests/invoke_large_request.cc", + "tests/keepalive_timeout.cc", + "tests/large_metadata.cc", + "tests/max_concurrent_streams.cc", + "tests/max_connection_age.cc", + "tests/max_connection_idle.cc", + "tests/max_message_length.cc", + "tests/negative_deadline.cc", + "tests/no_logging.cc", + "tests/no_op.cc", + "tests/payload.cc", + "tests/ping.cc", + "tests/ping_pong_streaming.cc", + "tests/proxy_auth.cc", + "tests/registered_call.cc", + "tests/request_with_flags.cc", + "tests/request_with_payload.cc", + "tests/resource_quota_server.cc", + "tests/retry.cc", + "tests/retry_cancel_after_first_attempt_starts.cc", + "tests/retry_cancel_during_delay.cc", + "tests/retry_cancel_with_multiple_send_batches.cc", + "tests/retry_cancellation.cc", + "tests/retry_disabled.cc", + "tests/retry_exceeds_buffer_size_in_delay.cc", + "tests/retry_exceeds_buffer_size_in_initial_batch.cc", + "tests/retry_exceeds_buffer_size_in_subsequent_batch.cc", + "tests/retry_lb_drop.cc", + "tests/retry_lb_fail.cc", + "tests/retry_non_retriable_status.cc", + "tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc", + "tests/retry_per_attempt_recv_timeout.cc", + "tests/retry_per_attempt_recv_timeout_on_last_attempt.cc", + "tests/retry_recv_initial_metadata.cc", + "tests/retry_recv_message.cc", + "tests/retry_recv_message_replay.cc", + "tests/retry_recv_trailing_metadata_error.cc", + "tests/retry_send_initial_metadata_refs.cc", + "tests/retry_send_op_fails.cc", + "tests/retry_send_recv_batch.cc", + "tests/retry_server_pushback_delay.cc", + "tests/retry_server_pushback_disabled.cc", + "tests/retry_streaming.cc", + "tests/retry_streaming_after_commit.cc", + "tests/retry_streaming_succeeds_before_replay_finished.cc", + "tests/retry_throttled.cc", + "tests/retry_too_many_attempts.cc", + "tests/retry_transparent_goaway.cc", + "tests/retry_transparent_max_concurrent_streams.cc", + "tests/retry_transparent_not_sent_on_wire.cc", + "tests/retry_unref_before_finish.cc", + "tests/retry_unref_before_recv.cc", + "tests/server_finishes_request.cc", + "tests/server_streaming.cc", + "tests/shutdown_finishes_calls.cc", + "tests/shutdown_finishes_tags.cc", + "tests/simple_delayed_request.cc", + "tests/simple_metadata.cc", + "tests/simple_request.cc", + "tests/streaming_error_response.cc", + "tests/trailing_metadata.cc", + "tests/write_buffering.cc", + "tests/write_buffering_at_end.cc", + ], + data = [ + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", + ], + external_deps = [ + "absl/status", + "absl/status:statusor", + "absl/strings", + "absl/strings:str_format", + "absl/types:optional", + "gtest", + ], + shard_count = 50, + tags = ["core_end2end_test"], + deps = [ + "cq_verifier", + "end2end_test_lib", + "fixture_support", + "http_proxy", + "proxy", + "//:channel_stack_builder", + "//:config", + "//:config_vars", + "//:debug_location", + "//:exec_ctx", + "//:gpr", + "//:grpc_authorization_provider", + "//:grpc_public_hdrs", + "//:grpc_security_base", + "//:grpc_trace", + "//:grpc_unsecure", + "//:orphanable", + "//:promise", + "//:ref_counted_ptr", + "//:stats", + "//src/core:arena_promise", + "//src/core:bitset", + "//src/core:channel_args", + "//src/core:channel_fwd", + "//src/core:channel_init", + "//src/core:channel_stack_type", + "//src/core:closure", + "//src/core:error", + "//src/core:grpc_authorization_base", + "//src/core:grpc_fake_credentials", + "//src/core:iomgr_port", + "//src/core:json", + "//src/core:lb_policy", + "//src/core:lb_policy_factory", + "//src/core:no_destruct", + "//src/core:notification", + "//src/core:slice", + "//src/core:stats_data", + "//src/core:status_helper", + "//src/core:time", + "//test/core/util:grpc_test_util", + "//test/core/util:test_lb_policies", + ], +) + grpc_cc_test( name = "bad_server_response_test", srcs = ["bad_server_response_test.cc"], @@ -267,8 +461,6 @@ grpc_cc_test( ], ) -grpc_end2end_tests() - grpc_cc_test( name = "h2_ssl_cert_test", srcs = [ @@ -276,21 +468,29 @@ grpc_cc_test( "h2_ssl_cert_test.cc", ], external_deps = [ + "absl/memory", + "absl/strings", "absl/types:optional", + "absl/types:variant", "gtest", "libcrypto", ], language = "C++", deps = [ "cq_verifier", + "end2end_test_lib", "fixture_support", "ssl_test_data", "//:config_vars", + "//:debug_location", "//:gpr", "//:grpc", "//:grpc_public_hdrs", "//:grpc_security_base", + "//src/core:bitset", "//src/core:channel_args", + "//src/core:slice", + "//src/core:time", "//test/core/util:grpc_test_util", ], ) diff --git a/test/core/end2end/README b/test/core/end2end/README deleted file mode 100644 index 51cc144039d..00000000000 --- a/test/core/end2end/README +++ /dev/null @@ -1,7 +0,0 @@ -Each fixture (under fixtures/) is paired with each test (under tests/) and -forms a complete end-to-end test. - -To add a new test or fixture: -- add the code to the relevant directory -- update generate_tests.bzl to reflect the change -- regenerate projects diff --git a/test/core/end2end/cq_verifier.cc b/test/core/end2end/cq_verifier.cc index 0be24f53d57..67e71626a04 100644 --- a/test/core/end2end/cq_verifier.cc +++ b/test/core/end2end/cq_verifier.cc @@ -33,6 +33,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" +#include "gtest/gtest.h" #include #include @@ -196,7 +197,9 @@ std::string TagStr(void* tag) { namespace grpc_core { -CqVerifier::CqVerifier(grpc_completion_queue* cq) : cq_(cq) {} +CqVerifier::CqVerifier(grpc_completion_queue* cq, + absl::AnyInvocable fail) + : cq_(cq), fail_(std::move(fail)) {} CqVerifier::~CqVerifier() { Verify(); } @@ -209,30 +212,66 @@ std::string CqVerifier::Expectation::ToString() const { return absl::StrCat("success=", success ? "true" : "false"); }, [](Maybe) { return std::string("maybe"); }, - [](AnyStatus) { return std::string("any success value"); })); + [](AnyStatus) { return std::string("any success value"); }, + [](PerformAction) { return std::string("perform some action"); }, + [](MaybePerformAction) { + return std::string("maybe perform action"); + })); } -std::string CqVerifier::ToString() const { +std::vector CqVerifier::ToStrings() const { std::vector expectations; expectations.reserve(expectations_.size()); for (const auto& e : expectations_) { expectations.push_back(e.ToString()); } - return absl::StrJoin(expectations, "\n"); + return expectations; +} + +std::string CqVerifier::ToString() const { + return absl::StrJoin(ToStrings(), "\n"); } void CqVerifier::FailNoEventReceived(const SourceLocation& location) const { - Crash(absl::StrFormat("[%s:%d] no event received, but expected:%s", - location.file(), location.line(), ToString().c_str())); + fail_(Failure{location, "No event received", ToStrings()}); } void CqVerifier::FailUnexpectedEvent(grpc_event* ev, const SourceLocation& location) const { - gpr_log(GPR_ERROR, "[%s:%d] cq returned unexpected event: %s", - location.file(), location.line(), grpc_event_string(ev).c_str()); - Crash(absl::StrFormat("expected tags:\n%s", ToString().c_str())); + fail_(Failure{location, + absl::StrCat("Unexpected event: ", grpc_event_string(ev)), + ToStrings()}); +} + +void CqVerifier::FailUsingGprCrash(const Failure& failure) { + Crash(absl::StrCat("[", failure.location.file(), ":", failure.location.line(), + "] ", failure.message, "\nexpected:\n", + absl::StrJoin(failure.expected, "\n"))); } +void CqVerifier::FailUsingGtestFail(const Failure& failure) { + std::string message = absl::StrCat(" ", failure.message); + if (!failure.expected.empty()) { + absl::StrAppend(&message, "\n expected:\n"); + for (const auto& line : failure.expected) { + absl::StrAppend(&message, " ", line, "\n"); + } + } else { + absl::StrAppend(&message, "\n expected nothing"); + } + ADD_FAILURE_AT(failure.location.file(), failure.location.line()) << message; +} + +namespace { +bool IsMaybe(const CqVerifier::ExpectedResult& r) { + return Match( + r, [](bool) { return false; }, [](CqVerifier::Maybe) { return true; }, + [](CqVerifier::AnyStatus) { return false; }, + [](const CqVerifier::PerformAction&) { return false; }, + [](const CqVerifier::MaybePerformAction&) { return true; }); +} +} // namespace + void CqVerifier::Verify(Duration timeout, SourceLocation location) { const gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(timeout.millis()); @@ -254,6 +293,14 @@ void CqVerifier::Verify(Duration timeout, SourceLocation location) { [ev](AnyStatus a) { if (a.result != nullptr) *a.result = ev.success; return true; + }, + [ev](const PerformAction& action) { + action.action(ev.success); + return true; + }, + [ev](const MaybePerformAction& action) { + action.action(ev.success); + return true; }); if (!expected) { FailUnexpectedEvent(&ev, location); @@ -267,16 +314,14 @@ void CqVerifier::Verify(Duration timeout, SourceLocation location) { } expectations_.erase( std::remove_if(expectations_.begin(), expectations_.end(), - [](const Expectation& e) { - return absl::holds_alternative(e.result); - }), + [](const Expectation& e) { return IsMaybe(e.result); }), expectations_.end()); if (!expectations_.empty()) FailNoEventReceived(location); } bool CqVerifier::AllMaybes() const { for (const auto& e : expectations_) { - if (!absl::holds_alternative(e.result)) return false; + if (!IsMaybe(e.result)) return false; } return true; } @@ -293,7 +338,7 @@ void CqVerifier::VerifyEmpty(Duration timeout, SourceLocation location) { void CqVerifier::Expect(void* tag, ExpectedResult result, SourceLocation location) { - expectations_.push_back(Expectation{location, tag, result}); + expectations_.push_back(Expectation{location, tag, std::move(result)}); } } // namespace grpc_core diff --git a/test/core/end2end/cq_verifier.h b/test/core/end2end/cq_verifier.h index d92e6de1b2e..85f32351e8f 100644 --- a/test/core/end2end/cq_verifier.h +++ b/test/core/end2end/cq_verifier.h @@ -21,9 +21,11 @@ #include +#include #include #include +#include "absl/functional/any_invocable.h" #include "absl/types/variant.h" #include @@ -48,10 +50,34 @@ class CqVerifier { struct AnyStatus { bool* result = nullptr; }; + // PerformAction - expect the tag, and run a function based on the result + struct PerformAction { + std::function action; + }; + // MaybePerformAction - run a function if a tag is seen + struct MaybePerformAction { + std::function action; + }; + + using ExpectedResult = + absl::variant; + + struct Failure { + SourceLocation location; + std::string message; + std::vector expected; + }; - using ExpectedResult = absl::variant; + static void FailUsingGprCrash(const Failure& failure); + static void FailUsingGtestFail(const Failure& failure); - explicit CqVerifier(grpc_completion_queue* cq); + // Allow customizing the failure handler + // For legacy tests we should use FailUsingGprCrash (the default) + // For gtest based tests we should start migrating to FailUsingGtestFail which + // will produce nicer failure messages. + explicit CqVerifier( + grpc_completion_queue* cq, + absl::AnyInvocable fail = FailUsingGprCrash); ~CqVerifier(); CqVerifier(const CqVerifier&) = delete; @@ -74,6 +100,7 @@ class CqVerifier { SourceLocation location = SourceLocation()); std::string ToString() const; + std::vector ToStrings() const; static void* tag(intptr_t t) { return reinterpret_cast(t); } @@ -93,6 +120,7 @@ class CqVerifier { grpc_completion_queue* const cq_; std::vector expectations_; + mutable absl::AnyInvocable fail_; }; } // namespace grpc_core diff --git a/test/core/end2end/end2end_test_main.cc b/test/core/end2end/end2end_test_main.cc new file mode 100644 index 00000000000..ddab93c07c9 --- /dev/null +++ b/test/core/end2end/end2end_test_main.cc @@ -0,0 +1,1070 @@ +// Copyright 2022 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/str_format.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/config/config_vars.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/host_port.h" +#include "src/core/lib/gprpp/no_destruct.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/iomgr/port.h" +#include "src/core/lib/security/credentials/fake/fake_credentials.h" +#include "test/core/end2end/end2end_tests.h" +#include "test/core/end2end/fixtures/h2_oauth2_common.h" +#include "test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h" +#include "test/core/end2end/fixtures/h2_ssl_tls_common.h" +#include "test/core/end2end/fixtures/h2_tls_common.h" +#include "test/core/end2end/fixtures/http_proxy_fixture.h" +#include "test/core/end2end/fixtures/inproc_fixture.h" +#include "test/core/end2end/fixtures/local_util.h" +#include "test/core/end2end/fixtures/proxy.h" +#include "test/core/end2end/fixtures/secure_fixture.h" +#include "test/core/end2end/fixtures/sockpair_fixture.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +// IWYU pragma: no_include + +#ifdef GRPC_POSIX_SOCKET +#include + +#include "src/core/lib/iomgr/socket_utils_posix.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" +#endif + +#ifdef GRPC_POSIX_WAKEUP_FD +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#endif + +#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem" +#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key" + +namespace grpc_core { + +namespace { + +std::atomic unique{0}; + +void ProcessAuthFailure(void* state, grpc_auth_context* /*ctx*/, + const grpc_metadata* /*md*/, size_t /*md_count*/, + grpc_process_auth_metadata_done_cb cb, + void* user_data) { + GPR_ASSERT(state == nullptr); + cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); +} + +void AddFailAuthCheckIfNeeded(const ChannelArgs& args, + grpc_server_credentials* creds) { + if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { + grpc_auth_metadata_processor processor = {ProcessAuthFailure, nullptr, + nullptr}; + grpc_server_credentials_set_auth_metadata_processor(creds, processor); + } +} + +} // namespace + +class CensusFixture : public CoreTestFixture { + private: + grpc_server* MakeServer(const ChannelArgs& args) override { + grpc_server_credentials* server_creds = + grpc_insecure_server_credentials_create(); + auto* server = grpc_server_create( + args.Set(GRPC_ARG_ENABLE_CENSUS, true).ToC().get(), nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + GPR_ASSERT( + grpc_server_add_http2_port(server, localaddr_.c_str(), server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(server); + return server; + } + grpc_channel* MakeClient(const ChannelArgs& args) override { + auto* creds = grpc_insecure_credentials_create(); + auto* client = + grpc_channel_create(localaddr_.c_str(), creds, + args.Set(GRPC_ARG_ENABLE_CENSUS, true).ToC().get()); + grpc_channel_credentials_release(creds); + return client; + } + const std::string localaddr_ = + JoinHostPort("localhost", grpc_pick_unused_port_or_die()); +}; + +class CompressionFixture : public CoreTestFixture { + private: + grpc_server* MakeServer(const ChannelArgs& args) override { + auto* server = grpc_server_create( + args.SetIfUnset(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, + GRPC_COMPRESS_GZIP) + .ToC() + .get(), + nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + grpc_server_credentials* server_creds = + grpc_insecure_server_credentials_create(); + GPR_ASSERT( + grpc_server_add_http2_port(server, localaddr_.c_str(), server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(server); + return server; + } + grpc_channel* MakeClient(const ChannelArgs& args) override { + grpc_channel_credentials* creds = grpc_insecure_credentials_create(); + auto* client = grpc_channel_create( + localaddr_.c_str(), creds, + args.SetIfUnset(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, + GRPC_COMPRESS_GZIP) + .ToC() + .get()); + grpc_channel_credentials_release(creds); + return client; + } + + std::string localaddr_ = + JoinHostPort("localhost", grpc_pick_unused_port_or_die()); +}; + +class FakesecFixture : public SecureFixture { + private: + grpc_channel_credentials* MakeClientCreds(const ChannelArgs&) override { + return grpc_fake_transport_security_credentials_create(); + } + grpc_server_credentials* MakeServerCreds(const ChannelArgs& args) override { + grpc_server_credentials* fake_ts_creds = + grpc_fake_transport_security_server_credentials_create(); + AddFailAuthCheckIfNeeded(args, fake_ts_creds); + return fake_ts_creds; + } +}; + +class InsecureCredsFixture : public InsecureFixture { + private: + grpc_server_credentials* MakeServerCreds(const ChannelArgs& args) override { + auto* creds = grpc_insecure_server_credentials_create(); + AddFailAuthCheckIfNeeded(args, creds); + return creds; + } +}; + +class SockpairWithMinstackFixture : public SockpairFixture { + public: + using SockpairFixture::SockpairFixture; + + private: + ChannelArgs MutateClientArgs(ChannelArgs args) override { + return args.Set(GRPC_ARG_MINIMAL_STACK, true); + } + ChannelArgs MutateServerArgs(ChannelArgs args) override { + return args.Set(GRPC_ARG_MINIMAL_STACK, true); + } +}; + +class Sockpair1Byte : public SockpairFixture { + public: + Sockpair1Byte() + : SockpairFixture(ChannelArgs() + .Set(GRPC_ARG_TCP_READ_CHUNK_SIZE, 1) + .Set(GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE, 1) + .Set(GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE, 1)) { + g_fixture_slowdown_factor = 2; + } + ~Sockpair1Byte() override { g_fixture_slowdown_factor = 1; } + + private: + ChannelArgs MutateClientArgs(ChannelArgs args) override { + return args.Set(GRPC_ARG_MINIMAL_STACK, true); + } + ChannelArgs MutateServerArgs(ChannelArgs args) override { + return args.Set(GRPC_ARG_MINIMAL_STACK, true); + } +}; + +#ifdef GRPC_POSIX_SOCKET + +class FdFixture : public CoreTestFixture { + public: + FdFixture() { create_sockets(fd_pair_); } + + private: + grpc_server* MakeServer(const ChannelArgs& args) override { + ExecCtx exec_ctx; + auto* server = grpc_server_create(args.ToC().get(), nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + grpc_server_start(server); + grpc_server_credentials* creds = grpc_insecure_server_credentials_create(); + grpc_server_add_channel_from_fd(server, fd_pair_[1], creds); + grpc_server_credentials_release(creds); + return server; + } + grpc_channel* MakeClient(const ChannelArgs& args) override { + ExecCtx exec_ctx; + grpc_channel_credentials* creds = grpc_insecure_credentials_create(); + auto* client = grpc_channel_create_from_fd("fixture_client", fd_pair_[0], + creds, args.ToC().get()); + grpc_channel_credentials_release(creds); + return client; + } + + static void create_sockets(int sv[2]) { + int flags; + grpc_create_socketpair_if_unix(sv); + flags = fcntl(sv[0], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); + flags = fcntl(sv[1], F_GETFL, 0); + GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); + GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == + absl::OkStatus()); + GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == + absl::OkStatus()); + } + + int fd_pair_[2]; +}; +#endif + +class NoRetryFixture : public InsecureFixture { + private: + ChannelArgs MutateClientArgs(ChannelArgs args) override { + return args.Set(GRPC_ARG_ENABLE_RETRIES, false); + } +}; + +class HttpProxyFilter : public CoreTestFixture { + public: + explicit HttpProxyFilter(const ChannelArgs& client_args) + : proxy_(grpc_end2end_http_proxy_create(client_args.ToC().get())) {} + ~HttpProxyFilter() override { + // Need to shut down the proxy users before closing the proxy (otherwise we + // become stuck). + ShutdownClient(); + ShutdownServer(); + grpc_end2end_http_proxy_destroy(proxy_); + } + + private: + grpc_server* MakeServer(const ChannelArgs& args) override { + auto* server = grpc_server_create(args.ToC().get(), nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + grpc_server_credentials* server_creds = + grpc_insecure_server_credentials_create(); + GPR_ASSERT( + grpc_server_add_http2_port(server, server_addr_.c_str(), server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(server); + return server; + } + + grpc_channel* MakeClient(const ChannelArgs& args) override { + // If testing for proxy auth, add credentials to proxy uri + absl::optional proxy_auth_str = + args.GetOwnedString(GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + std::string proxy_uri; + if (!proxy_auth_str.has_value()) { + proxy_uri = absl::StrFormat( + "http://%s", grpc_end2end_http_proxy_get_proxy_name(proxy_)); + } else { + proxy_uri = + absl::StrFormat("http://%s@%s", proxy_auth_str->c_str(), + grpc_end2end_http_proxy_get_proxy_name(proxy_)); + } + grpc_channel_credentials* creds = grpc_insecure_credentials_create(); + auto* client = grpc_channel_create( + server_addr_.c_str(), creds, + args.Set(GRPC_ARG_HTTP_PROXY, proxy_uri).ToC().get()); + grpc_channel_credentials_release(creds); + GPR_ASSERT(client); + return client; + } + + std::string server_addr_ = + JoinHostPort("localhost", grpc_pick_unused_port_or_die()); + grpc_end2end_http_proxy* proxy_; +}; + +class ProxyFixture : public CoreTestFixture { + public: + ProxyFixture(const ChannelArgs& client_args, const ChannelArgs& server_args) + : proxy_(grpc_end2end_proxy_create(&proxy_def_, client_args.ToC().get(), + server_args.ToC().get())) {} + ~ProxyFixture() override { grpc_end2end_proxy_destroy(proxy_); } + + private: + static grpc_server* CreateProxyServer(const char* port, + const grpc_channel_args* server_args) { + grpc_server* s = grpc_server_create(server_args, nullptr); + grpc_server_credentials* server_creds = + grpc_insecure_server_credentials_create(); + GPR_ASSERT(grpc_server_add_http2_port(s, port, server_creds)); + grpc_server_credentials_release(server_creds); + return s; + } + + static grpc_channel* CreateProxyClient(const char* target, + const grpc_channel_args* client_args) { + grpc_channel_credentials* creds = grpc_insecure_credentials_create(); + grpc_channel* channel = grpc_channel_create(target, creds, client_args); + grpc_channel_credentials_release(creds); + return channel; + } + + grpc_server* MakeServer(const ChannelArgs& args) override { + auto* server = grpc_server_create(args.ToC().get(), nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + grpc_server_credentials* server_creds = + grpc_insecure_server_credentials_create(); + GPR_ASSERT(grpc_server_add_http2_port( + server, grpc_end2end_proxy_get_server_port(proxy_), server_creds)); + grpc_server_credentials_release(server_creds); + grpc_server_start(server); + return server; + } + + grpc_channel* MakeClient(const ChannelArgs& args) override { + grpc_channel_credentials* creds = grpc_insecure_credentials_create(); + auto* client = grpc_channel_create( + grpc_end2end_proxy_get_client_target(proxy_), creds, args.ToC().get()); + grpc_channel_credentials_release(creds); + GPR_ASSERT(client); + return client; + } + const grpc_end2end_proxy_def proxy_def_ = {CreateProxyServer, + CreateProxyClient}; + grpc_end2end_proxy* proxy_; +}; + +class SslProxyFixture : public CoreTestFixture { + public: + SslProxyFixture(const ChannelArgs& client_args, + const ChannelArgs& server_args) + : proxy_(grpc_end2end_proxy_create(&proxy_def_, client_args.ToC().get(), + server_args.ToC().get())) {} + ~SslProxyFixture() override { grpc_end2end_proxy_destroy(proxy_); } + + private: + static grpc_server* CreateProxyServer(const char* port, + const grpc_channel_args* server_args) { + grpc_server* s = grpc_server_create(server_args, nullptr); + grpc_slice cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); + const char* server_cert = + reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); + const char* server_key = + reinterpret_cast GRPC_SLICE_START_PTR(key_slice); + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; + grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( + nullptr, &pem_key_cert_pair, 1, 0, nullptr); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + GPR_ASSERT(grpc_server_add_http2_port(s, port, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + return s; + } + + static grpc_channel* CreateProxyClient(const char* target, + const grpc_channel_args* client_args) { + grpc_channel* channel; + grpc_channel_credentials* ssl_creds = + grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); + grpc_arg ssl_name_override = { + GRPC_ARG_STRING, + const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), + {const_cast("foo.test.google.fr")}}; + const grpc_channel_args* new_client_args = + grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); + channel = grpc_channel_create(target, ssl_creds, new_client_args); + grpc_channel_credentials_release(ssl_creds); + { + ExecCtx exec_ctx; + grpc_channel_args_destroy(new_client_args); + } + return channel; + } + + grpc_server* MakeServer(const ChannelArgs& args) override { + grpc_slice cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "load_file", grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); + const char* server_cert = + reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); + const char* server_key = + reinterpret_cast GRPC_SLICE_START_PTR(key_slice); + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; + grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( + nullptr, &pem_key_cert_pair, 1, 0, nullptr); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { + grpc_auth_metadata_processor processor = {ProcessAuthFailure, nullptr, + nullptr}; + grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); + } + + auto* server = grpc_server_create(args.ToC().get(), nullptr); + grpc_server_register_completion_queue(server, cq(), nullptr); + GPR_ASSERT(grpc_server_add_http2_port( + server, grpc_end2end_proxy_get_server_port(proxy_), ssl_creds)); + grpc_server_credentials_release(ssl_creds); + grpc_server_start(server); + return server; + } + + grpc_channel* MakeClient(const ChannelArgs& args) override { + grpc_channel_credentials* ssl_creds = + grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); + auto* client = grpc_channel_create( + grpc_end2end_proxy_get_client_target(proxy_), ssl_creds, + args.Set(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, "foo.test.google.fr") + .ToC() + .get()); + GPR_ASSERT(client != nullptr); + grpc_channel_credentials_release(ssl_creds); + return client; + } + const grpc_end2end_proxy_def proxy_def_ = {CreateProxyServer, + CreateProxyClient}; + grpc_end2end_proxy* proxy_; +}; + +class FixtureWithTracing final : public CoreTestFixture { + public: + explicit FixtureWithTracing(std::unique_ptr fixture) + : fixture_(std::move(fixture)) { + // g_fixture_slowdown_factor = 10; + EXPECT_FALSE(grpc_tracer_set_enabled("doesnt-exist", 0)); + EXPECT_TRUE(grpc_tracer_set_enabled("http", 1)); + EXPECT_TRUE(grpc_tracer_set_enabled("all", 1)); + } + ~FixtureWithTracing() override { + saved_trace_flags_.Restore(); + // g_fixture_slowdown_factor = 1; + } + + grpc_server* MakeServer(const ChannelArgs& args) override { + return fixture_->MakeServer(args); + } + + grpc_channel* MakeClient(const ChannelArgs& args) override { + return fixture_->MakeClient(args); + } + + private: + SavedTraceFlags saved_trace_flags_; + std::unique_ptr fixture_; +}; + +#ifdef GRPC_POSIX_WAKEUP_FD +class InsecureFixtureWithPipeForWakeupFd : public InsecureFixture { + public: + InsecureFixtureWithPipeForWakeupFd() + : old_value_(std::exchange(grpc_allow_specialized_wakeup_fd, 0)) {} + + ~InsecureFixtureWithPipeForWakeupFd() override { + grpc_allow_specialized_wakeup_fd = old_value_; + } + + private: + const int old_value_; +}; +#endif + +std::vector AllConfigs() { + std::vector configs { +#ifdef GRPC_POSIX_SOCKET + CoreTestConfiguration{"Chttp2Fd", FEATURE_MASK_IS_HTTP2, nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }}, +#endif + CoreTestConfiguration{ + "Chttp2FakeSecurityFullstack", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }}, + CoreTestConfiguration{ + "Chttp2Fullstack", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + return std::make_unique(); + }}, + CoreTestConfiguration{ + "Chttp2FullstackCompression", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }}, +#ifdef GPR_LINUX + CoreTestConfiguration{ + "Chttp2FullstackLocalAbstractUdsPercentEncoded", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + return std::make_unique( + absl::StrFormat( + "unix-abstract:grpc_fullstack_test.%%00.%d.%" PRId64 + ".%" PRId32 ".%d", + getpid(), now.tv_sec, now.tv_nsec, + unique.fetch_add(1, std::memory_order_relaxed)), + UDS); + }}, +#endif + CoreTestConfiguration{"Chttp2FullstackLocalIpv4", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + int port = grpc_pick_unused_port_or_die(); + return std::make_unique( + JoinHostPort("127.0.0.1", port), LOCAL_TCP); + }}, + CoreTestConfiguration{"Chttp2FullstackLocalIpv6", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + int port = grpc_pick_unused_port_or_die(); + return std::make_unique( + JoinHostPort("[::1]", port), LOCAL_TCP); + }}, +#ifdef GRPC_HAVE_UNIX_SOCKET + CoreTestConfiguration{ + "Chttp2FullstackLocalUdsPercentEncoded", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + return std::make_unique( + absl::StrFormat( + "unix:/tmp/grpc_fullstack_test.%%25.%d.%" PRId64 + ".%" PRId32 ".%d", + getpid(), now.tv_sec, now.tv_nsec, + unique.fetch_add(1, std::memory_order_relaxed)), + UDS); + }}, + CoreTestConfiguration{ + "Chttp2FullstackLocalUds", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + return std::make_unique( + absl::StrFormat( + "unix:/tmp/grpc_fullstack_test.%d.%" PRId64 ".%" PRId32 + ".%d", + getpid(), now.tv_sec, now.tv_nsec, + unique.fetch_add(1, std::memory_order_relaxed)), + UDS); + }}, +#endif + CoreTestConfiguration{"Chttp2FullstackNoRetry", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_IS_HTTP2 | + FEATURE_MASK_DOES_NOT_SUPPORT_RETRY, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + return std::make_unique(); + }}, + CoreTestConfiguration{ + "Chttp2FullstackWithCensus", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }}, + CoreTestConfiguration{ + "Chttp2FullstackWithProxy", + FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& client_args, const ChannelArgs& server_args) { + return std::make_unique(client_args, server_args); + }}, + CoreTestConfiguration{ + "Chttp2HttpProxy", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& client_args, const ChannelArgs&) { + return std::make_unique(client_args); + }}, + CoreTestConfiguration{ + "Chttp2SslProxy", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs& client_args, const ChannelArgs& server_args) { + return std::make_unique(client_args, + server_args); + }}, + CoreTestConfiguration{ + "Chttp2InsecureCredentials", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE | + FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }, + }, + CoreTestConfiguration{ + "Chttp2SimpleSslWithOauth2FullstackTls12", + FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(grpc_tls_version::TLS1_2); + }}, + CoreTestConfiguration{ + "Chttp2SimpleSslWithOauth2FullstackTls13", + FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(grpc_tls_version::TLS1_3); + }}, + CoreTestConfiguration{ + "Chttp2SimplSslFullstackTls12", + FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(grpc_tls_version::TLS1_2); + }}, + CoreTestConfiguration{ + "Chttp2SimplSslFullstackTls13", + FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST | + FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(grpc_tls_version::TLS1_3); + }}, + CoreTestConfiguration{ + "Chttp2SocketPair", FEATURE_MASK_IS_HTTP2, nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(ChannelArgs()); + }}, + CoreTestConfiguration{ + "Chttp2SocketPair1ByteAtATime", + FEATURE_MASK_IS_HTTP2 | FEATURE_MASK_1BYTE_AT_A_TIME, nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + ChannelArgs() + .Set(GRPC_ARG_TCP_READ_CHUNK_SIZE, 1) + .Set(GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE, 1) + .Set(GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE, 1)); + }}, + CoreTestConfiguration{ + "Chttp2SocketPairMinstack", + FEATURE_MASK_IS_HTTP2 | FEATURE_MASK_IS_MINSTACK, nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + ChannelArgs()); + }}, + CoreTestConfiguration{ + "Inproc", + FEATURE_MASK_DOES_NOT_SUPPORT_WRITE_BUFFERING, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(); + }, + }, + CoreTestConfiguration{ + "Chttp2SslCredReloadTls12", + FEATURE_MASK_IS_SECURE | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(TLS1_2); + }}, + CoreTestConfiguration{ + "Chttp2SslCredReloadTls13", + FEATURE_MASK_IS_SECURE | FEATURE_MASK_IS_HTTP2 | + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique(TLS1_3); + }}, + CoreTestConfiguration{ + // client: certificate watcher provider + async external verifier + // server: certificate watcher provider + async external verifier + // extra: TLS 1.3 + "Chttp2CertWatcherProviderAsyncVerifierTls13", + kH2TLSFeatureMask, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + SecurityPrimitives::TlsVersion::V_13, + SecurityPrimitives::ProviderType::FILE_PROVIDER, + SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER); + }, + }, + CoreTestConfiguration{ + // client: certificate watcher provider + hostname verifier + // server: certificate watcher provider + sync external verifier + // extra: TLS 1.2 + "Chttp2CertWatcherProviderSyncVerifierTls12", + kH2TLSFeatureMask, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + SecurityPrimitives::TlsVersion::V_12, + SecurityPrimitives::ProviderType::FILE_PROVIDER, + SecurityPrimitives::VerifierType::HOSTNAME_VERIFIER); + }, + }, + CoreTestConfiguration{ + // client: static data provider + sync external verifier + // server: static data provider + sync external verifier + // extra: TLS 1.2 + "Chttp2SimpleSslFullstack", + kH2TLSFeatureMask, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + SecurityPrimitives::TlsVersion::V_12, + SecurityPrimitives::ProviderType::STATIC_PROVIDER, + SecurityPrimitives::VerifierType::EXTERNAL_SYNC_VERIFIER); + }, + }, + CoreTestConfiguration{ + // client: static data provider + async external verifier + // server: static data provider + async external verifier + // extra: TLS 1.3 + "Chttp2StaticProviderAsyncVerifierTls13", + kH2TLSFeatureMask, + "foo.test.google.fr", + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + SecurityPrimitives::TlsVersion::V_13, + SecurityPrimitives::ProviderType::STATIC_PROVIDER, + SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER); + }, + }, +#ifdef GPR_LINUX + CoreTestConfiguration{ + "Chttp2FullstackUdsAbstractNamespace", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + return std::make_unique(absl::StrFormat( + "unix-abstract:grpc_fullstack_test.%d.%" PRId64 ".%" PRId32 + ".%d", + getpid(), now.tv_sec, now.tv_nsec, + unique.fetch_add(1, std::memory_order_relaxed))); + }}, +#endif +#ifdef GRPC_HAVE_UNIX_SOCKET + CoreTestConfiguration{ + "Chttp2FullstackUds", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + return std::make_unique(absl::StrFormat( + "unix:/tmp/grpc_fullstack_test.%d.%" PRId64 ".%" PRId32 ".%d", + getpid(), now.tv_sec, now.tv_nsec, + unique.fetch_add(1, std::memory_order_relaxed))); + }}, +#endif +// TODO(ctiller): these got inadvertently disabled when the project +// switched to Bazel in 2016, and have not been re-enabled since and are now +// quite broken. We should re-enable them however, as they provide defense in +// depth that enabling tracers is safe. When doing so, we'll need to re-enable +// the windows setvbuf statement in main(). +#if 0 + CoreTestConfiguration{ + "Chttp2SocketPairWithTrace", + FEATURE_MASK_IS_HTTP2 | FEATURE_MASK_ENABLES_TRACES, nullptr, + [](const ChannelArgs&, const ChannelArgs&) { + return std::make_unique( + std::make_unique(ChannelArgs())); + }}, + CoreTestConfiguration{"Chttp2FullstackWithTrace", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | + FEATURE_MASK_IS_HTTP2 | + FEATURE_MASK_ENABLES_TRACES, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + return std::make_unique( + std::make_unique()); + }}, +#endif +#ifdef GRPC_POSIX_WAKEUP_FD + CoreTestConfiguration{ + "Chttp2FullstackWithPipeWakeup", + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2, + nullptr, + [](const ChannelArgs& /*client_args*/, + const ChannelArgs& /*server_args*/) { + return std::make_unique(); + }}, +#endif + }; + std::sort(configs.begin(), configs.end(), + [](const CoreTestConfiguration& a, const CoreTestConfiguration& b) { + return strcmp(a.name, b.name) < 0; + }); + return configs; +} + +// A ConfigQuery queries a database a set of test configurations +// that match some criteria. +class ConfigQuery { + public: + ConfigQuery() = default; + ConfigQuery(const ConfigQuery&) = delete; + ConfigQuery& operator=(const ConfigQuery&) = delete; + // Enforce that the returned configurations have the given features. + ConfigQuery& EnforceFeatures(uint32_t features) { + enforce_features_ |= features; + return *this; + } + // Envorce that the returned configurations do not have the given features. + ConfigQuery& ExcludeFeatures(uint32_t features) { + exclude_features_ |= features; + return *this; + } + // Enforce that the returned configurations have the given name (regex). + ConfigQuery& AllowName(const std::string& name) { + allowed_names_.emplace_back( + std::regex(name, std::regex_constants::ECMAScript)); + return *this; + } + // Enforce that the returned configurations do not have the given name + // (regex). + ConfigQuery& ExcludeName(const std::string& name) { + excluded_names_.emplace_back( + std::regex(name, std::regex_constants::ECMAScript)); + return *this; + } + + auto Run() const { + static NoDestruct> kConfigs( + AllConfigs()); + std::vector out; + for (const CoreTestConfiguration& config : *kConfigs) { + if ((config.feature_mask & enforce_features_) == enforce_features_ && + (config.feature_mask & exclude_features_) == 0) { + bool allowed = allowed_names_.empty(); + for (const std::regex& re : allowed_names_) { + if (std::regex_match(config.name, re)) { + allowed = true; + break; + } + } + for (const std::regex& re : excluded_names_) { + if (std::regex_match(config.name, re)) { + allowed = false; + break; + } + } + if (allowed) { + out.push_back(&config); + } + } + } + return ::testing::ValuesIn(out); + } + + private: + uint32_t enforce_features_ = 0; + uint32_t exclude_features_ = 0; + std::vector allowed_names_; + std::vector excluded_names_; +}; + +// Produce a nice name to print next to each test case for gtest. +inline const char* NameFromConfig( + const ::testing::TestParamInfo& config) { + return config.param->name; +} + +INSTANTIATE_TEST_SUITE_P(CoreEnd2endTests, CoreEnd2endTest, ConfigQuery().Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + SecureEnd2endTests, SecureEnd2endTest, + ConfigQuery().EnforceFeatures(FEATURE_MASK_IS_SECURE).Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P(CoreLargeSendTests, CoreLargeSendTest, + ConfigQuery() + .ExcludeFeatures(FEATURE_MASK_1BYTE_AT_A_TIME | + FEATURE_MASK_ENABLES_TRACES) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + CoreDeadlineTests, CoreDeadlineTest, + ConfigQuery().ExcludeFeatures(FEATURE_MASK_IS_MINSTACK).Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + CoreClientChannelTests, CoreClientChannelTest, + ConfigQuery().EnforceFeatures(FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL).Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + Http2SingleHopTests, Http2SingleHopTest, + ConfigQuery() + .EnforceFeatures(FEATURE_MASK_IS_HTTP2) + .ExcludeFeatures(FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_ENABLES_TRACES) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + RetryTests, RetryTest, + ConfigQuery() + .EnforceFeatures(FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) + .ExcludeFeatures(FEATURE_MASK_DOES_NOT_SUPPORT_RETRY) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + WriteBufferingTests, WriteBufferingTest, + ConfigQuery() + .ExcludeFeatures(FEATURE_MASK_DOES_NOT_SUPPORT_WRITE_BUFFERING) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + Http2Tests, Http2Test, + ConfigQuery().EnforceFeatures(FEATURE_MASK_IS_HTTP2).Run(), NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + RetryHttp2Tests, RetryHttp2Test, + ConfigQuery() + .EnforceFeatures(FEATURE_MASK_IS_HTTP2 | + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) + .ExcludeFeatures(FEATURE_MASK_DOES_NOT_SUPPORT_RETRY | + FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + ResourceQuotaTests, ResourceQuotaTest, + ConfigQuery() + .ExcludeFeatures(FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | + FEATURE_MASK_1BYTE_AT_A_TIME) + .ExcludeName("Chttp2.*Uds.*") + .ExcludeName("Chttp2HttpProxy") + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + PerCallCredsTests, PerCallCredsTest, + ConfigQuery() + .EnforceFeatures(FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + PerCallCredsOnInsecureTests, PerCallCredsOnInsecureTest, + ConfigQuery() + .EnforceFeatures( + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE) + .Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P( + NoLoggingTests, NoLoggingTest, + ConfigQuery().ExcludeFeatures(FEATURE_MASK_ENABLES_TRACES).Run(), + NameFromConfig); + +INSTANTIATE_TEST_SUITE_P(ProxyAuthTests, ProxyAuthTest, + ConfigQuery().AllowName("Chttp2HttpProxy").Run(), + NameFromConfig); + +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(&argc, argv); + ::testing::InitGoogleTest(&argc, argv); + // TODO(ctiller): make this per fixture? + grpc_core::ConfigVars::Overrides overrides; + overrides.default_ssl_roots_file_path = CA_CERT_PATH; + grpc_core::ConfigVars::SetOverrides(overrides); + return RUN_ALL_TESTS(); +} diff --git a/test/core/end2end/end2end_test_utils.cc b/test/core/end2end/end2end_test_utils.cc deleted file mode 100644 index a3c6b41f238..00000000000 --- a/test/core/end2end/end2end_test_utils.cc +++ /dev/null @@ -1,49 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include "test/core/end2end/end2end_tests.h" - -const char* get_host_override_string(const char* str, - const CoreTestConfiguration& config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - return str; - } else { - return nullptr; - } -} - -const grpc_slice* get_host_override_slice(const char* str, - const CoreTestConfiguration& config) { - const char* r = get_host_override_string(str, config); - if (r != nullptr) { - static grpc_slice ret; - ret = grpc_slice_from_static_string(r); - return &ret; - } - return nullptr; -} - -void validate_host_override_string(const char* pattern, grpc_slice str, - const CoreTestConfiguration& config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - GPR_ASSERT(0 == grpc_slice_str_cmp(str, pattern)); - } -} diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index da3bf9e91bc..8c6ba5598f8 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -17,783 +17,261 @@ // // -// This file is auto-generated - #include "test/core/end2end/end2end_tests.h" -#include -#include +#include + +#include "absl/memory/memory.h" +#include "absl/random/random.h" + +#include +#include +#include -#include "absl/strings/str_format.h" +#include "src/core/lib/compression/message_compress.h" +#include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/gprpp/no_destruct.h" +#include "test/core/end2end/cq_verifier.h" -#include +namespace grpc_core { + +Slice RandomSlice(size_t length) { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + std::vector output; + output.resize(length); + for (i = 0; i < length; ++i) { + output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; + } + return Slice::FromCopiedBuffer(output); +} + +Slice RandomBinarySlice(size_t length) { + size_t i; + std::vector output; + output.resize(length); + for (i = 0; i < length; ++i) { + output[i] = rand(); + } + return Slice::FromCopiedBuffer(output); +} -#include "src/core/lib/gprpp/crash.h" +ByteBufferUniquePtr ByteBufferFromSlice(Slice slice) { + return ByteBufferUniquePtr( + grpc_raw_byte_buffer_create(const_cast(&slice.c_slice()), 1), + grpc_byte_buffer_destroy); +} -static bool g_pre_init_called = false; +namespace { +absl::optional FindInMetadataArray(const grpc_metadata_array& md, + absl::string_view key) { + for (size_t i = 0; i < md.count; i++) { + if (key == StringViewFromSlice(md.metadata[i].key)) { + return std::string(StringViewFromSlice(md.metadata[i].value)); + } + } + return absl::nullopt; +} +} // namespace -extern void authority_not_supported(const CoreTestConfiguration& config); -extern void authority_not_supported_pre_init(void); -extern void bad_hostname(const CoreTestConfiguration& config); -extern void bad_hostname_pre_init(void); -extern void bad_ping(const CoreTestConfiguration& config); -extern void bad_ping_pre_init(void); -extern void binary_metadata(const CoreTestConfiguration& config); -extern void binary_metadata_pre_init(void); -extern void call_creds(const CoreTestConfiguration& config); -extern void call_creds_pre_init(void); -extern void call_host_override(const CoreTestConfiguration& config); -extern void call_host_override_pre_init(void); -extern void cancel_after_accept(const CoreTestConfiguration& config); -extern void cancel_after_accept_pre_init(void); -extern void cancel_after_client_done(const CoreTestConfiguration& config); -extern void cancel_after_client_done_pre_init(void); -extern void cancel_after_invoke(const CoreTestConfiguration& config); -extern void cancel_after_invoke_pre_init(void); -extern void cancel_after_round_trip(const CoreTestConfiguration& config); -extern void cancel_after_round_trip_pre_init(void); -extern void cancel_before_invoke(const CoreTestConfiguration& config); -extern void cancel_before_invoke_pre_init(void); -extern void cancel_in_a_vacuum(const CoreTestConfiguration& config); -extern void cancel_in_a_vacuum_pre_init(void); -extern void cancel_with_status(const CoreTestConfiguration& config); -extern void cancel_with_status_pre_init(void); -extern void channelz(const CoreTestConfiguration& config); -extern void channelz_pre_init(void); -extern void client_streaming(const CoreTestConfiguration& config); -extern void client_streaming_pre_init(void); -extern void compressed_payload(const CoreTestConfiguration& config); -extern void compressed_payload_pre_init(void); -extern void connectivity(const CoreTestConfiguration& config); -extern void connectivity_pre_init(void); -extern void default_host(const CoreTestConfiguration& config); -extern void default_host_pre_init(void); -extern void disappearing_server(const CoreTestConfiguration& config); -extern void disappearing_server_pre_init(void); -extern void empty_batch(const CoreTestConfiguration& config); -extern void empty_batch_pre_init(void); -extern void filter_causes_close(const CoreTestConfiguration& config); -extern void filter_causes_close_pre_init(void); -extern void filter_context(const CoreTestConfiguration& config); -extern void filter_context_pre_init(void); -extern void filter_init_fails(const CoreTestConfiguration& config); -extern void filter_init_fails_pre_init(void); -extern void filter_latency(const CoreTestConfiguration& config); -extern void filter_latency_pre_init(void); -extern void filter_status_code(const CoreTestConfiguration& config); -extern void filter_status_code_pre_init(void); -extern void filtered_metadata(const CoreTestConfiguration& config); -extern void filtered_metadata_pre_init(void); -extern void graceful_server_shutdown(const CoreTestConfiguration& config); -extern void graceful_server_shutdown_pre_init(void); -extern void grpc_authz(const CoreTestConfiguration& config); -extern void grpc_authz_pre_init(void); -extern void high_initial_seqno(const CoreTestConfiguration& config); -extern void high_initial_seqno_pre_init(void); -extern void hpack_size(const CoreTestConfiguration& config); -extern void hpack_size_pre_init(void); -extern void invoke_large_request(const CoreTestConfiguration& config); -extern void invoke_large_request_pre_init(void); -extern void keepalive_timeout(const CoreTestConfiguration& config); -extern void keepalive_timeout_pre_init(void); -extern void large_metadata(const CoreTestConfiguration& config); -extern void large_metadata_pre_init(void); -extern void max_concurrent_streams(const CoreTestConfiguration& config); -extern void max_concurrent_streams_pre_init(void); -extern void max_connection_age(const CoreTestConfiguration& config); -extern void max_connection_age_pre_init(void); -extern void max_connection_idle(const CoreTestConfiguration& config); -extern void max_connection_idle_pre_init(void); -extern void max_message_length(const CoreTestConfiguration& config); -extern void max_message_length_pre_init(void); -extern void negative_deadline(const CoreTestConfiguration& config); -extern void negative_deadline_pre_init(void); -extern void no_logging(const CoreTestConfiguration& config); -extern void no_logging_pre_init(void); -extern void no_op(const CoreTestConfiguration& config); -extern void no_op_pre_init(void); -extern void payload(const CoreTestConfiguration& config); -extern void payload_pre_init(void); -extern void ping(const CoreTestConfiguration& config); -extern void ping_pre_init(void); -extern void ping_pong_streaming(const CoreTestConfiguration& config); -extern void ping_pong_streaming_pre_init(void); -extern void proxy_auth(const CoreTestConfiguration& config); -extern void proxy_auth_pre_init(void); -extern void registered_call(const CoreTestConfiguration& config); -extern void registered_call_pre_init(void); -extern void request_with_flags(const CoreTestConfiguration& config); -extern void request_with_flags_pre_init(void); -extern void request_with_payload(const CoreTestConfiguration& config); -extern void request_with_payload_pre_init(void); -extern void resource_quota_server(const CoreTestConfiguration& config); -extern void resource_quota_server_pre_init(void); -extern void retry(const CoreTestConfiguration& config); -extern void retry_pre_init(void); -extern void retry_cancel_after_first_attempt_starts(const CoreTestConfiguration& config); -extern void retry_cancel_after_first_attempt_starts_pre_init(void); -extern void retry_cancel_during_delay(const CoreTestConfiguration& config); -extern void retry_cancel_during_delay_pre_init(void); -extern void retry_cancel_with_multiple_send_batches(const CoreTestConfiguration& config); -extern void retry_cancel_with_multiple_send_batches_pre_init(void); -extern void retry_cancellation(const CoreTestConfiguration& config); -extern void retry_cancellation_pre_init(void); -extern void retry_disabled(const CoreTestConfiguration& config); -extern void retry_disabled_pre_init(void); -extern void retry_exceeds_buffer_size_in_delay(const CoreTestConfiguration& config); -extern void retry_exceeds_buffer_size_in_delay_pre_init(void); -extern void retry_exceeds_buffer_size_in_initial_batch(const CoreTestConfiguration& config); -extern void retry_exceeds_buffer_size_in_initial_batch_pre_init(void); -extern void retry_exceeds_buffer_size_in_subsequent_batch(const CoreTestConfiguration& config); -extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void); -extern void retry_lb_drop(const CoreTestConfiguration& config); -extern void retry_lb_drop_pre_init(void); -extern void retry_lb_fail(const CoreTestConfiguration& config); -extern void retry_lb_fail_pre_init(void); -extern void retry_non_retriable_status(const CoreTestConfiguration& config); -extern void retry_non_retriable_status_pre_init(void); -extern void retry_non_retriable_status_before_recv_trailing_metadata_started(const CoreTestConfiguration& config); -extern void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(void); -extern void retry_per_attempt_recv_timeout(const CoreTestConfiguration& config); -extern void retry_per_attempt_recv_timeout_pre_init(void); -extern void retry_per_attempt_recv_timeout_on_last_attempt(const CoreTestConfiguration& config); -extern void retry_per_attempt_recv_timeout_on_last_attempt_pre_init(void); -extern void retry_recv_initial_metadata(const CoreTestConfiguration& config); -extern void retry_recv_initial_metadata_pre_init(void); -extern void retry_recv_message(const CoreTestConfiguration& config); -extern void retry_recv_message_pre_init(void); -extern void retry_recv_message_replay(const CoreTestConfiguration& config); -extern void retry_recv_message_replay_pre_init(void); -extern void retry_recv_trailing_metadata_error(const CoreTestConfiguration& config); -extern void retry_recv_trailing_metadata_error_pre_init(void); -extern void retry_send_initial_metadata_refs(const CoreTestConfiguration& config); -extern void retry_send_initial_metadata_refs_pre_init(void); -extern void retry_send_op_fails(const CoreTestConfiguration& config); -extern void retry_send_op_fails_pre_init(void); -extern void retry_send_recv_batch(const CoreTestConfiguration& config); -extern void retry_send_recv_batch_pre_init(void); -extern void retry_server_pushback_delay(const CoreTestConfiguration& config); -extern void retry_server_pushback_delay_pre_init(void); -extern void retry_server_pushback_disabled(const CoreTestConfiguration& config); -extern void retry_server_pushback_disabled_pre_init(void); -extern void retry_streaming(const CoreTestConfiguration& config); -extern void retry_streaming_pre_init(void); -extern void retry_streaming_after_commit(const CoreTestConfiguration& config); -extern void retry_streaming_after_commit_pre_init(void); -extern void retry_streaming_succeeds_before_replay_finished(const CoreTestConfiguration& config); -extern void retry_streaming_succeeds_before_replay_finished_pre_init(void); -extern void retry_throttled(const CoreTestConfiguration& config); -extern void retry_throttled_pre_init(void); -extern void retry_too_many_attempts(const CoreTestConfiguration& config); -extern void retry_too_many_attempts_pre_init(void); -extern void retry_transparent_goaway(const CoreTestConfiguration& config); -extern void retry_transparent_goaway_pre_init(void); -extern void retry_transparent_max_concurrent_streams(const CoreTestConfiguration& config); -extern void retry_transparent_max_concurrent_streams_pre_init(void); -extern void retry_transparent_not_sent_on_wire(const CoreTestConfiguration& config); -extern void retry_transparent_not_sent_on_wire_pre_init(void); -extern void retry_unref_before_finish(const CoreTestConfiguration& config); -extern void retry_unref_before_finish_pre_init(void); -extern void retry_unref_before_recv(const CoreTestConfiguration& config); -extern void retry_unref_before_recv_pre_init(void); -extern void server_finishes_request(const CoreTestConfiguration& config); -extern void server_finishes_request_pre_init(void); -extern void server_streaming(const CoreTestConfiguration& config); -extern void server_streaming_pre_init(void); -extern void shutdown_finishes_calls(const CoreTestConfiguration& config); -extern void shutdown_finishes_calls_pre_init(void); -extern void shutdown_finishes_tags(const CoreTestConfiguration& config); -extern void shutdown_finishes_tags_pre_init(void); -extern void simple_delayed_request(const CoreTestConfiguration& config); -extern void simple_delayed_request_pre_init(void); -extern void simple_metadata(const CoreTestConfiguration& config); -extern void simple_metadata_pre_init(void); -extern void simple_request(const CoreTestConfiguration& config); -extern void simple_request_pre_init(void); -extern void streaming_error_response(const CoreTestConfiguration& config); -extern void streaming_error_response_pre_init(void); -extern void trailing_metadata(const CoreTestConfiguration& config); -extern void trailing_metadata_pre_init(void); -extern void write_buffering(const CoreTestConfiguration& config); -extern void write_buffering_pre_init(void); -extern void write_buffering_at_end(const CoreTestConfiguration& config); -extern void write_buffering_at_end_pre_init(void); +void CoreEnd2endTest::SetUp() { + CoreConfiguration::Reset(); + initialized_ = false; +} -void grpc_end2end_tests_pre_init(void) { - GPR_ASSERT(!g_pre_init_called); - g_pre_init_called = true; - authority_not_supported_pre_init(); - bad_hostname_pre_init(); - bad_ping_pre_init(); - binary_metadata_pre_init(); - call_creds_pre_init(); - call_host_override_pre_init(); - cancel_after_accept_pre_init(); - cancel_after_client_done_pre_init(); - cancel_after_invoke_pre_init(); - cancel_after_round_trip_pre_init(); - cancel_before_invoke_pre_init(); - cancel_in_a_vacuum_pre_init(); - cancel_with_status_pre_init(); - channelz_pre_init(); - client_streaming_pre_init(); - compressed_payload_pre_init(); - connectivity_pre_init(); - default_host_pre_init(); - disappearing_server_pre_init(); - empty_batch_pre_init(); - filter_causes_close_pre_init(); - filter_context_pre_init(); - filter_init_fails_pre_init(); - filter_latency_pre_init(); - filter_status_code_pre_init(); - filtered_metadata_pre_init(); - graceful_server_shutdown_pre_init(); - grpc_authz_pre_init(); - high_initial_seqno_pre_init(); - hpack_size_pre_init(); - invoke_large_request_pre_init(); - keepalive_timeout_pre_init(); - large_metadata_pre_init(); - max_concurrent_streams_pre_init(); - max_connection_age_pre_init(); - max_connection_idle_pre_init(); - max_message_length_pre_init(); - negative_deadline_pre_init(); - no_logging_pre_init(); - no_op_pre_init(); - payload_pre_init(); - ping_pre_init(); - ping_pong_streaming_pre_init(); - proxy_auth_pre_init(); - registered_call_pre_init(); - request_with_flags_pre_init(); - request_with_payload_pre_init(); - resource_quota_server_pre_init(); - retry_pre_init(); - retry_cancel_after_first_attempt_starts_pre_init(); - retry_cancel_during_delay_pre_init(); - retry_cancel_with_multiple_send_batches_pre_init(); - retry_cancellation_pre_init(); - retry_disabled_pre_init(); - retry_exceeds_buffer_size_in_delay_pre_init(); - retry_exceeds_buffer_size_in_initial_batch_pre_init(); - retry_exceeds_buffer_size_in_subsequent_batch_pre_init(); - retry_lb_drop_pre_init(); - retry_lb_fail_pre_init(); - retry_non_retriable_status_pre_init(); - retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(); - retry_per_attempt_recv_timeout_pre_init(); - retry_per_attempt_recv_timeout_on_last_attempt_pre_init(); - retry_recv_initial_metadata_pre_init(); - retry_recv_message_pre_init(); - retry_recv_message_replay_pre_init(); - retry_recv_trailing_metadata_error_pre_init(); - retry_send_initial_metadata_refs_pre_init(); - retry_send_op_fails_pre_init(); - retry_send_recv_batch_pre_init(); - retry_server_pushback_delay_pre_init(); - retry_server_pushback_disabled_pre_init(); - retry_streaming_pre_init(); - retry_streaming_after_commit_pre_init(); - retry_streaming_succeeds_before_replay_finished_pre_init(); - retry_throttled_pre_init(); - retry_too_many_attempts_pre_init(); - retry_transparent_goaway_pre_init(); - retry_transparent_max_concurrent_streams_pre_init(); - retry_transparent_not_sent_on_wire_pre_init(); - retry_unref_before_finish_pre_init(); - retry_unref_before_recv_pre_init(); - server_finishes_request_pre_init(); - server_streaming_pre_init(); - shutdown_finishes_calls_pre_init(); - shutdown_finishes_tags_pre_init(); - simple_delayed_request_pre_init(); - simple_metadata_pre_init(); - simple_request_pre_init(); - streaming_error_response_pre_init(); - trailing_metadata_pre_init(); - write_buffering_pre_init(); - write_buffering_at_end_pre_init(); +void CoreEnd2endTest::TearDown() { + const bool do_shutdown = fixture_ != nullptr; + cq_verifier_.reset(); + fixture_.reset(); + if (do_shutdown) grpc_shutdown_blocking(); + initialized_ = false; } -// NOLINTNEXTLINE(readability-function-size) -void grpc_end2end_tests(int argc, char **argv, - const CoreTestConfiguration& config) { - int i; +absl::optional CoreEnd2endTest::IncomingMetadata::Get( + absl::string_view key) const { + return FindInMetadataArray(*metadata_, key); +} - GPR_ASSERT(g_pre_init_called); +grpc_op CoreEnd2endTest::IncomingMetadata::MakeOp() { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_RECV_INITIAL_METADATA; + op.data.recv_initial_metadata.recv_initial_metadata = metadata_.get(); + return op; +} - if (argc <= 1) { - authority_not_supported(config); - bad_hostname(config); - bad_ping(config); - binary_metadata(config); - call_creds(config); - call_host_override(config); - cancel_after_accept(config); - cancel_after_client_done(config); - cancel_after_invoke(config); - cancel_after_round_trip(config); - cancel_before_invoke(config); - cancel_in_a_vacuum(config); - cancel_with_status(config); - channelz(config); - client_streaming(config); - compressed_payload(config); - connectivity(config); - default_host(config); - disappearing_server(config); - empty_batch(config); - filter_causes_close(config); - filter_context(config); - filter_init_fails(config); - filter_latency(config); - filter_status_code(config); - filtered_metadata(config); - graceful_server_shutdown(config); - grpc_authz(config); - high_initial_seqno(config); - hpack_size(config); - invoke_large_request(config); - keepalive_timeout(config); - large_metadata(config); - max_concurrent_streams(config); - max_connection_age(config); - max_connection_idle(config); - max_message_length(config); - negative_deadline(config); - no_logging(config); - no_op(config); - payload(config); - ping(config); - ping_pong_streaming(config); - proxy_auth(config); - registered_call(config); - request_with_flags(config); - request_with_payload(config); - resource_quota_server(config); - retry(config); - retry_cancel_after_first_attempt_starts(config); - retry_cancel_during_delay(config); - retry_cancel_with_multiple_send_batches(config); - retry_cancellation(config); - retry_disabled(config); - retry_exceeds_buffer_size_in_delay(config); - retry_exceeds_buffer_size_in_initial_batch(config); - retry_exceeds_buffer_size_in_subsequent_batch(config); - retry_lb_drop(config); - retry_lb_fail(config); - retry_non_retriable_status(config); - retry_non_retriable_status_before_recv_trailing_metadata_started(config); - retry_per_attempt_recv_timeout(config); - retry_per_attempt_recv_timeout_on_last_attempt(config); - retry_recv_initial_metadata(config); - retry_recv_message(config); - retry_recv_message_replay(config); - retry_recv_trailing_metadata_error(config); - retry_send_initial_metadata_refs(config); - retry_send_op_fails(config); - retry_send_recv_batch(config); - retry_server_pushback_delay(config); - retry_server_pushback_disabled(config); - retry_streaming(config); - retry_streaming_after_commit(config); - retry_streaming_succeeds_before_replay_finished(config); - retry_throttled(config); - retry_too_many_attempts(config); - retry_transparent_goaway(config); - retry_transparent_max_concurrent_streams(config); - retry_transparent_not_sent_on_wire(config); - retry_unref_before_finish(config); - retry_unref_before_recv(config); - server_finishes_request(config); - server_streaming(config); - shutdown_finishes_calls(config); - shutdown_finishes_tags(config); - simple_delayed_request(config); - simple_metadata(config); - simple_request(config); - streaming_error_response(config); - trailing_metadata(config); - write_buffering(config); - write_buffering_at_end(config); - return; +std::string CoreEnd2endTest::IncomingMessage::payload() const { + Slice out; + if (payload_->data.raw.compression > GRPC_COMPRESS_NONE) { + grpc_slice_buffer decompressed_buffer; + grpc_slice_buffer_init(&decompressed_buffer); + GPR_ASSERT(grpc_msg_decompress(payload_->data.raw.compression, + &payload_->data.raw.slice_buffer, + &decompressed_buffer)); + grpc_byte_buffer* rbb = grpc_raw_byte_buffer_create( + decompressed_buffer.slices, decompressed_buffer.count); + grpc_byte_buffer_reader reader; + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, rbb)); + out = Slice(grpc_byte_buffer_reader_readall(&reader)); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(rbb); + grpc_slice_buffer_destroy(&decompressed_buffer); + } else { + grpc_byte_buffer_reader reader; + GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, payload_)); + out = Slice(grpc_byte_buffer_reader_readall(&reader)); + grpc_byte_buffer_reader_destroy(&reader); } + return std::string(out.begin(), out.end()); +} - for (i = 1; i < argc; i++) { - if (0 == strcmp("authority_not_supported", argv[i])) { - authority_not_supported(config); - continue; - } - if (0 == strcmp("bad_hostname", argv[i])) { - bad_hostname(config); - continue; - } - if (0 == strcmp("bad_ping", argv[i])) { - bad_ping(config); - continue; - } - if (0 == strcmp("binary_metadata", argv[i])) { - binary_metadata(config); - continue; - } - if (0 == strcmp("call_creds", argv[i])) { - call_creds(config); - continue; - } - if (0 == strcmp("call_host_override", argv[i])) { - call_host_override(config); - continue; - } - if (0 == strcmp("cancel_after_accept", argv[i])) { - cancel_after_accept(config); - continue; - } - if (0 == strcmp("cancel_after_client_done", argv[i])) { - cancel_after_client_done(config); - continue; - } - if (0 == strcmp("cancel_after_invoke", argv[i])) { - cancel_after_invoke(config); - continue; - } - if (0 == strcmp("cancel_after_round_trip", argv[i])) { - cancel_after_round_trip(config); - continue; - } - if (0 == strcmp("cancel_before_invoke", argv[i])) { - cancel_before_invoke(config); - continue; - } - if (0 == strcmp("cancel_in_a_vacuum", argv[i])) { - cancel_in_a_vacuum(config); - continue; - } - if (0 == strcmp("cancel_with_status", argv[i])) { - cancel_with_status(config); - continue; - } - if (0 == strcmp("channelz", argv[i])) { - channelz(config); - continue; - } - if (0 == strcmp("client_streaming", argv[i])) { - client_streaming(config); - continue; - } - if (0 == strcmp("compressed_payload", argv[i])) { - compressed_payload(config); - continue; - } - if (0 == strcmp("connectivity", argv[i])) { - connectivity(config); - continue; - } - if (0 == strcmp("default_host", argv[i])) { - default_host(config); - continue; - } - if (0 == strcmp("disappearing_server", argv[i])) { - disappearing_server(config); - continue; - } - if (0 == strcmp("empty_batch", argv[i])) { - empty_batch(config); - continue; - } - if (0 == strcmp("filter_causes_close", argv[i])) { - filter_causes_close(config); - continue; - } - if (0 == strcmp("filter_context", argv[i])) { - filter_context(config); - continue; - } - if (0 == strcmp("filter_init_fails", argv[i])) { - filter_init_fails(config); - continue; - } - if (0 == strcmp("filter_latency", argv[i])) { - filter_latency(config); - continue; - } - if (0 == strcmp("filter_status_code", argv[i])) { - filter_status_code(config); - continue; - } - if (0 == strcmp("filtered_metadata", argv[i])) { - filtered_metadata(config); - continue; - } - if (0 == strcmp("graceful_server_shutdown", argv[i])) { - graceful_server_shutdown(config); - continue; - } - if (0 == strcmp("grpc_authz", argv[i])) { - grpc_authz(config); - continue; - } - if (0 == strcmp("high_initial_seqno", argv[i])) { - high_initial_seqno(config); - continue; - } - if (0 == strcmp("hpack_size", argv[i])) { - hpack_size(config); - continue; - } - if (0 == strcmp("invoke_large_request", argv[i])) { - invoke_large_request(config); - continue; - } - if (0 == strcmp("keepalive_timeout", argv[i])) { - keepalive_timeout(config); - continue; - } - if (0 == strcmp("large_metadata", argv[i])) { - large_metadata(config); - continue; - } - if (0 == strcmp("max_concurrent_streams", argv[i])) { - max_concurrent_streams(config); - continue; - } - if (0 == strcmp("max_connection_age", argv[i])) { - max_connection_age(config); - continue; - } - if (0 == strcmp("max_connection_idle", argv[i])) { - max_connection_idle(config); - continue; - } - if (0 == strcmp("max_message_length", argv[i])) { - max_message_length(config); - continue; - } - if (0 == strcmp("negative_deadline", argv[i])) { - negative_deadline(config); - continue; - } - if (0 == strcmp("no_logging", argv[i])) { - no_logging(config); - continue; - } - if (0 == strcmp("no_op", argv[i])) { - no_op(config); - continue; - } - if (0 == strcmp("payload", argv[i])) { - payload(config); - continue; - } - if (0 == strcmp("ping", argv[i])) { - ping(config); - continue; - } - if (0 == strcmp("ping_pong_streaming", argv[i])) { - ping_pong_streaming(config); - continue; - } - if (0 == strcmp("proxy_auth", argv[i])) { - proxy_auth(config); - continue; - } - if (0 == strcmp("registered_call", argv[i])) { - registered_call(config); - continue; - } - if (0 == strcmp("request_with_flags", argv[i])) { - request_with_flags(config); - continue; - } - if (0 == strcmp("request_with_payload", argv[i])) { - request_with_payload(config); - continue; - } - if (0 == strcmp("resource_quota_server", argv[i])) { - resource_quota_server(config); - continue; - } - if (0 == strcmp("retry", argv[i])) { - retry(config); - continue; - } - if (0 == strcmp("retry_cancel_after_first_attempt_starts", argv[i])) { - retry_cancel_after_first_attempt_starts(config); - continue; - } - if (0 == strcmp("retry_cancel_during_delay", argv[i])) { - retry_cancel_during_delay(config); - continue; - } - if (0 == strcmp("retry_cancel_with_multiple_send_batches", argv[i])) { - retry_cancel_with_multiple_send_batches(config); - continue; - } - if (0 == strcmp("retry_cancellation", argv[i])) { - retry_cancellation(config); - continue; - } - if (0 == strcmp("retry_disabled", argv[i])) { - retry_disabled(config); - continue; - } - if (0 == strcmp("retry_exceeds_buffer_size_in_delay", argv[i])) { - retry_exceeds_buffer_size_in_delay(config); - continue; - } - if (0 == strcmp("retry_exceeds_buffer_size_in_initial_batch", argv[i])) { - retry_exceeds_buffer_size_in_initial_batch(config); - continue; - } - if (0 == strcmp("retry_exceeds_buffer_size_in_subsequent_batch", argv[i])) { - retry_exceeds_buffer_size_in_subsequent_batch(config); - continue; - } - if (0 == strcmp("retry_lb_drop", argv[i])) { - retry_lb_drop(config); - continue; - } - if (0 == strcmp("retry_lb_fail", argv[i])) { - retry_lb_fail(config); - continue; - } - if (0 == strcmp("retry_non_retriable_status", argv[i])) { - retry_non_retriable_status(config); - continue; - } - if (0 == strcmp("retry_non_retriable_status_before_recv_trailing_metadata_started", argv[i])) { - retry_non_retriable_status_before_recv_trailing_metadata_started(config); - continue; - } - if (0 == strcmp("retry_per_attempt_recv_timeout", argv[i])) { - retry_per_attempt_recv_timeout(config); - continue; - } - if (0 == strcmp("retry_per_attempt_recv_timeout_on_last_attempt", argv[i])) { - retry_per_attempt_recv_timeout_on_last_attempt(config); - continue; - } - if (0 == strcmp("retry_recv_initial_metadata", argv[i])) { - retry_recv_initial_metadata(config); - continue; - } - if (0 == strcmp("retry_recv_message", argv[i])) { - retry_recv_message(config); - continue; - } - if (0 == strcmp("retry_recv_message_replay", argv[i])) { - retry_recv_message_replay(config); - continue; - } - if (0 == strcmp("retry_recv_trailing_metadata_error", argv[i])) { - retry_recv_trailing_metadata_error(config); - continue; - } - if (0 == strcmp("retry_send_initial_metadata_refs", argv[i])) { - retry_send_initial_metadata_refs(config); - continue; - } - if (0 == strcmp("retry_send_op_fails", argv[i])) { - retry_send_op_fails(config); - continue; - } - if (0 == strcmp("retry_send_recv_batch", argv[i])) { - retry_send_recv_batch(config); - continue; - } - if (0 == strcmp("retry_server_pushback_delay", argv[i])) { - retry_server_pushback_delay(config); - continue; - } - if (0 == strcmp("retry_server_pushback_disabled", argv[i])) { - retry_server_pushback_disabled(config); - continue; - } - if (0 == strcmp("retry_streaming", argv[i])) { - retry_streaming(config); - continue; - } - if (0 == strcmp("retry_streaming_after_commit", argv[i])) { - retry_streaming_after_commit(config); - continue; - } - if (0 == strcmp("retry_streaming_succeeds_before_replay_finished", argv[i])) { - retry_streaming_succeeds_before_replay_finished(config); - continue; - } - if (0 == strcmp("retry_throttled", argv[i])) { - retry_throttled(config); - continue; - } - if (0 == strcmp("retry_too_many_attempts", argv[i])) { - retry_too_many_attempts(config); - continue; - } - if (0 == strcmp("retry_transparent_goaway", argv[i])) { - retry_transparent_goaway(config); - continue; - } - if (0 == strcmp("retry_transparent_max_concurrent_streams", argv[i])) { - retry_transparent_max_concurrent_streams(config); - continue; - } - if (0 == strcmp("retry_transparent_not_sent_on_wire", argv[i])) { - retry_transparent_not_sent_on_wire(config); - continue; - } - if (0 == strcmp("retry_unref_before_finish", argv[i])) { - retry_unref_before_finish(config); - continue; - } - if (0 == strcmp("retry_unref_before_recv", argv[i])) { - retry_unref_before_recv(config); - continue; - } - if (0 == strcmp("server_finishes_request", argv[i])) { - server_finishes_request(config); - continue; - } - if (0 == strcmp("server_streaming", argv[i])) { - server_streaming(config); - continue; - } - if (0 == strcmp("shutdown_finishes_calls", argv[i])) { - shutdown_finishes_calls(config); - continue; - } - if (0 == strcmp("shutdown_finishes_tags", argv[i])) { - shutdown_finishes_tags(config); - continue; - } - if (0 == strcmp("simple_delayed_request", argv[i])) { - simple_delayed_request(config); - continue; - } - if (0 == strcmp("simple_metadata", argv[i])) { - simple_metadata(config); - continue; - } - if (0 == strcmp("simple_request", argv[i])) { - simple_request(config); - continue; - } - if (0 == strcmp("streaming_error_response", argv[i])) { - streaming_error_response(config); - continue; - } - if (0 == strcmp("trailing_metadata", argv[i])) { - trailing_metadata(config); - continue; - } - if (0 == strcmp("write_buffering", argv[i])) { - write_buffering(config); - continue; - } - if (0 == strcmp("write_buffering_at_end", argv[i])) { - write_buffering_at_end(config); - continue; - } - grpc_core::Crash(absl::StrFormat( "not a test: '%s'", argv[i])); +grpc_op CoreEnd2endTest::IncomingMessage::MakeOp() { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_RECV_MESSAGE; + op.data.recv_message.recv_message = &payload_; + return op; +} + +absl::optional +CoreEnd2endTest::IncomingStatusOnClient::GetTrailingMetadata( + absl::string_view key) const { + return FindInMetadataArray(data_->trailing_metadata, key); +} + +grpc_op CoreEnd2endTest::IncomingStatusOnClient::MakeOp() { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op.data.recv_status_on_client.trailing_metadata = &data_->trailing_metadata; + op.data.recv_status_on_client.status = &data_->status; + op.data.recv_status_on_client.status_details = + const_cast(&data_->status_details.c_slice()); + op.data.recv_status_on_client.error_string = &data_->error_string; + return op; +} + +grpc_op CoreEnd2endTest::IncomingCloseOnServer::MakeOp() { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op.data.recv_close_on_server.cancelled = &cancelled_; + return op; +} + +CoreEnd2endTest::BatchBuilder& +CoreEnd2endTest::BatchBuilder::SendInitialMetadata( + std::initializer_list> md, + uint32_t flags, absl::optional compression_level) { + auto& v = Make>(); + for (const auto& p : md) { + grpc_metadata m; + m.key = Make(Slice::FromCopiedString(p.first)).c_slice(); + m.value = Make(Slice::FromCopiedString(p.second)).c_slice(); + v.push_back(m); + } + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_INITIAL_METADATA; + op.flags = flags; + op.data.send_initial_metadata.count = v.size(); + op.data.send_initial_metadata.metadata = v.data(); + if (compression_level.has_value()) { + op.data.send_initial_metadata.maybe_compression_level.is_set = 1; + op.data.send_initial_metadata.maybe_compression_level.level = + compression_level.value(); + } + ops_.push_back(op); + return *this; +} + +CoreEnd2endTest::BatchBuilder& CoreEnd2endTest::BatchBuilder::SendMessage( + Slice payload, uint32_t flags) { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_MESSAGE; + op.data.send_message.send_message = + Make(ByteBufferFromSlice(std::move(payload))).get(); + op.flags = flags; + ops_.push_back(op); + return *this; +} + +CoreEnd2endTest::BatchBuilder& +CoreEnd2endTest::BatchBuilder::SendCloseFromClient() { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + ops_.push_back(op); + return *this; +} + +CoreEnd2endTest::BatchBuilder& +CoreEnd2endTest::BatchBuilder::SendStatusFromServer( + grpc_status_code status, absl::string_view message, + std::initializer_list> md) { + auto& v = Make>(); + for (const auto& p : md) { + grpc_metadata m; + m.key = Make(Slice::FromCopiedString(p.first)).c_slice(); + m.value = Make(Slice::FromCopiedString(p.second)).c_slice(); + v.push_back(m); + } + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op.data.send_status_from_server.trailing_metadata_count = v.size(); + op.data.send_status_from_server.trailing_metadata = v.data(); + op.data.send_status_from_server.status = status; + op.data.send_status_from_server.status_details = &Make( + Make(Slice::FromCopiedString(message)).c_slice()); + ops_.push_back(op); + return *this; +} + +CoreEnd2endTest::BatchBuilder::~BatchBuilder() { + grpc_call_error err = grpc_call_start_batch(call_, ops_.data(), ops_.size(), + CqVerifier::tag(tag_), nullptr); + EXPECT_EQ(err, GRPC_CALL_OK) << grpc_call_error_to_string(err); +} + +CoreEnd2endTest::Call CoreEnd2endTest::ClientCallBuilder::Create() { + if (auto* u = absl::get_if(&call_selector_)) { + absl::optional host; + if (u->host.has_value()) host = Slice::FromCopiedString(*u->host); + test_.ForceInitialized(); + return Call(grpc_channel_create_call( + test_.fixture().client(), parent_call_, propagation_mask_, + test_.fixture().cq(), Slice::FromCopiedString(u->method).c_slice(), + host.has_value() ? &host->c_slice() : nullptr, deadline_, nullptr)); + } else { + return Call(grpc_channel_create_registered_call( + test_.fixture().client(), parent_call_, propagation_mask_, + test_.fixture().cq(), absl::get(call_selector_), deadline_, + nullptr)); } } + +CoreEnd2endTest::IncomingCall::IncomingCall(CoreEnd2endTest& test, int tag) + : impl_(std::make_unique()) { + test.ForceInitialized(); + grpc_server_request_call(test.fixture().server(), impl_->call.call_ptr(), + &impl_->call_details, &impl_->request_metadata, + test.fixture().cq(), test.fixture().cq(), + CqVerifier::tag(tag)); +} + +absl::optional CoreEnd2endTest::IncomingCall::GetInitialMetadata( + absl::string_view key) const { + return FindInMetadataArray(impl_->request_metadata, key); +} + +void CoreEnd2endTest::ForceInitialized() { + if (!initialized_) { + initialized_ = true; + fixture().InitServer(ChannelArgs()); + fixture().InitClient(ChannelArgs()); + } +} + +} // namespace grpc_core diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h index d635fdd4d6d..9ffdf4680f8 100644 --- a/test/core/end2end/end2end_tests.h +++ b/test/core/end2end/end2end_tests.h @@ -19,20 +19,46 @@ #ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H #define GRPC_TEST_CORE_END2END_END2END_TESTS_H +#include #include +#include #include +#include #include +#include +#include +#include +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "absl/types/variant.h" +#include "gtest/gtest.h" + +#include +#include #include -#include +#include +#include +#include +#include #include +#include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/bitset.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/surface/call_test_only.h" +#include "src/core/lib/surface/channel.h" +#include "test/core/end2end/cq_verifier.h" #include "test/core/util/test_config.h" // Test feature flags. -#define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1 +#define FEATURE_MASK_DOES_NOT_SUPPORT_RETRY 1 #define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2 // Feature mask supports call credentials with a minimum security level of // GRPC_PRIVACY_AND_INTEGRITY. @@ -42,12 +68,17 @@ #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE 8 #define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING 16 #define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL 32 -#define FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER 64 +#define FEATURE_MASK_IS_HTTP2 64 +#define FEATURE_MASK_ENABLES_TRACES 128 +#define FEATURE_MASK_1BYTE_AT_A_TIME 256 +#define FEATURE_MASK_DOES_NOT_SUPPORT_WRITE_BUFFERING 512 #define FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST 1024 -#define FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES 2048 +#define FEATURE_MASK_IS_MINSTACK 2048 +#define FEATURE_MASK_IS_SECURE 4096 #define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check" +namespace grpc_core { class CoreTestFixture { public: virtual ~CoreTestFixture() { @@ -62,12 +93,12 @@ class CoreTestFixture { grpc_server* server() { return server_; } grpc_channel* client() { return client_; } - void InitServer(const grpc_core::ChannelArgs& args) { + void InitServer(const ChannelArgs& args) { if (server_ != nullptr) ShutdownServer(); server_ = MakeServer(args); GPR_ASSERT(server_ != nullptr); } - void InitClient(const grpc_core::ChannelArgs& args) { + void InitClient(const ChannelArgs& args) { if (client_ != nullptr) ShutdownClient(); client_ = MakeClient(args); GPR_ASSERT(client_ != nullptr); @@ -96,14 +127,14 @@ class CoreTestFixture { client_ = nullptr; } + virtual grpc_server* MakeServer(const ChannelArgs& args) = 0; + virtual grpc_channel* MakeClient(const ChannelArgs& args) = 0; + protected: void SetServer(grpc_server* server); void SetClient(grpc_channel* client); private: - virtual grpc_server* MakeServer(const grpc_core::ChannelArgs& args) = 0; - virtual grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) = 0; - void DrainCq() { grpc_event ev; do { @@ -117,6 +148,12 @@ class CoreTestFixture { grpc_channel* client_ = nullptr; }; +Slice RandomSlice(size_t length); +Slice RandomBinarySlice(size_t length); +using ByteBufferUniquePtr = + std::unique_ptr; +ByteBufferUniquePtr ByteBufferFromSlice(Slice slice); + struct CoreTestConfiguration { // A descriptive name for this test fixture. const char* name; @@ -130,23 +167,584 @@ struct CoreTestConfiguration { const char* overridden_call_host; std::function( - const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args)> + const ChannelArgs& client_args, const ChannelArgs& server_args)> create_fixture; }; -void grpc_end2end_tests_pre_init(void); -void grpc_end2end_tests(int argc, char** argv, - const CoreTestConfiguration& config); +// Base class for e2e tests. +// +// Initialization: +// +// At the start of a test, nothing is initialized. CoreConfiguration is reset, +// and there's certainly no server nor client. +// A test can then register whatever builders it wants into the +// CoreConfiguration and have them picked up. If it does not, it will get the +// default CoreConfiguration. +// +// The test may choose to then create a client and server with InitClient() and +// InitServer(). It does not matter which order they are called, nor whether one +// or both are called. It's necessary to call these if the test demands that +// non-empty channel args should be passed to either the client or server. +// +// If a test does not call InitClient() or InitServer(), then upon the first +// call to either NewClientCall() or NewServerCall(), the client and server will +// be instantiated - this saves substantial boilerplate in the most common case +// for our tests. +// +// Notes: +// - older compilers fail matching absl::string_view with some gmock matchers on +// older compilers, and it's tremendously convenient to be able to do so. So +// we use std::string for return types here - performance isn't particularly +// important, so an extra copy is fine. +class CoreEnd2endTest + : public ::testing::TestWithParam { + public: + void SetUp() override; + void TearDown() override; + + class Call; + struct RegisteredCall { + void* p; + }; + + // CallBuilder - results in a call to either grpc_channel_create_call or + // grpc_channel_create_registered_call. + // Affords a fluent interface to specify optional arguments. + class ClientCallBuilder { + public: + ClientCallBuilder(CoreEnd2endTest& test, std::string method) + : test_(test), + call_selector_(UnregisteredCall{std::move(method), absl::nullopt}) {} + ClientCallBuilder(CoreEnd2endTest& test, RegisteredCall registered_call) + : test_(test), call_selector_(registered_call.p) {} + + // Specify the host (otherwise nullptr is passed) + ClientCallBuilder& Host(std::string host) { + absl::get(call_selector_).host = std::move(host); + return *this; + } + // Specify the timeout (otherwise gpr_inf_future is passed) - this time is + // scaled according to the test environment. + ClientCallBuilder& Timeout(Duration timeout) { + if (timeout == Duration::Infinity()) { + deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME); + return *this; + } + deadline_ = grpc_timeout_milliseconds_to_deadline(timeout.millis()); + return *this; + } + // Finally create the call. + Call Create(); + + private: + CoreEnd2endTest& test_; + struct UnregisteredCall { + std::string method; + absl::optional host; + }; + absl::variant call_selector_; + grpc_call* parent_call_ = nullptr; + uint32_t propagation_mask_ = GRPC_PROPAGATE_DEFAULTS; + gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_REALTIME); + }; + + // Receiving container for incoming metadata. + class IncomingMetadata { + public: + IncomingMetadata() = default; + ~IncomingMetadata() { + if (metadata_ != nullptr) grpc_metadata_array_destroy(metadata_.get()); + } + + // Lookup a metadata value by key. + absl::optional Get(absl::string_view key) const; + + // Make a GRPC_RECV_INITIAL_METADATA op - intended for the framework, not + // for tests. + grpc_op MakeOp(); + + private: + std::unique_ptr metadata_ = + std::make_unique( + grpc_metadata_array{0, 0, nullptr}); + }; + + // Receiving container for one incoming message. + class IncomingMessage { + public: + IncomingMessage() = default; + IncomingMessage(const IncomingMessage&) = delete; + IncomingMessage& operator=(const IncomingMessage&) = delete; + ~IncomingMessage() { + if (payload_ != nullptr) grpc_byte_buffer_destroy(payload_); + } + + // Get the payload of the message - concatenated together into a string for + // easy verification. + std::string payload() const; + // Check if the message is the end of the stream. + bool is_end_of_stream() const { return payload_ == nullptr; } + // Get the type of the message. + grpc_byte_buffer_type byte_buffer_type() const { return payload_->type; } + // Get the compression algorithm used for the message. + grpc_compression_algorithm compression() const { + return payload_->data.raw.compression; + } + + // Make a GRPC_OP_RECV_MESSAGE op - intended for the framework, not for + // tests. + grpc_op MakeOp(); + + private: + grpc_byte_buffer* payload_ = nullptr; + }; + + // Receiving container for incoming status on the client from the server. + class IncomingStatusOnClient { + public: + IncomingStatusOnClient() = default; + IncomingStatusOnClient(const IncomingStatusOnClient&) = delete; + IncomingStatusOnClient& operator=(const IncomingStatusOnClient&) = delete; + IncomingStatusOnClient(IncomingStatusOnClient&& other) noexcept = default; + IncomingStatusOnClient& operator=(IncomingStatusOnClient&& other) noexcept = + default; + ~IncomingStatusOnClient() { + if (data_ != nullptr) { + grpc_metadata_array_destroy(&data_->trailing_metadata); + gpr_free(const_cast(data_->error_string)); + } + } + + // Get the status code. + grpc_status_code status() const { return data_->status; } + // Get the status details. + std::string message() const { + return std::string(data_->status_details.as_string_view()); + } + // Get the error string. + std::string error_string() const { + return data_->error_string == nullptr ? "" : data_->error_string; + } + // Get a trailing metadata value by key. + absl::optional GetTrailingMetadata( + absl::string_view key) const; + + // Make a GRPC_OP_RECV_STATUS_ON_CLIENT op - intended for the framework, not + // for tests. + grpc_op MakeOp(); + + private: + struct Data { + grpc_metadata_array trailing_metadata{0, 0, nullptr}; + grpc_status_code status; + Slice status_details; + const char* error_string = nullptr; + }; + std::unique_ptr data_ = std::make_unique(); + }; + + // Receiving container for incoming status on the server from the client. + class IncomingCloseOnServer { + public: + IncomingCloseOnServer() = default; + IncomingCloseOnServer(const IncomingCloseOnServer&) = delete; + IncomingCloseOnServer& operator=(const IncomingCloseOnServer&) = delete; + + // Get the cancellation bit. + bool was_cancelled() const { return cancelled_ != 0; } + + // Make a GRPC_OP_RECV_CLOSE_ON_SERVER op - intended for the framework, not + // for tests. + grpc_op MakeOp(); + + private: + int cancelled_; + }; + + // Build one batch. Returned from NewBatch (use that to instantiate this!) + // Upon destruction of the BatchBuilder, the batch will be executed with any + // added batches. + class BatchBuilder { + public: + BatchBuilder(grpc_call* call, int tag) : call_(call), tag_(tag) {} + ~BatchBuilder(); + + BatchBuilder(const BatchBuilder&) = delete; + BatchBuilder& operator=(const BatchBuilder&) = delete; + BatchBuilder(BatchBuilder&&) noexcept = default; + + // Add a GRPC_OP_SEND_INITIAL_METADATA op. + // Optionally specify flags, compression level. + BatchBuilder& SendInitialMetadata( + std::initializer_list> + md, + uint32_t flags = 0, + absl::optional compression_level = + absl::nullopt); + + // Add a GRPC_OP_SEND_MESSAGE op. + BatchBuilder& SendMessage(Slice payload, uint32_t flags = 0); + BatchBuilder& SendMessage(absl::string_view payload, uint32_t flags = 0) { + return SendMessage(Slice::FromCopiedString(payload), flags); + } + + // Add a GRPC_OP_SEND_CLOSE_FROM_CLIENT op. + BatchBuilder& SendCloseFromClient(); + + // Add a GRPC_OP_SEND_STATUS_FROM_SERVER op. + BatchBuilder& SendStatusFromServer( + grpc_status_code status, absl::string_view message, + std::initializer_list> + md); + + // Add a GRPC_OP_RECV_INITIAL_METADATA op. + BatchBuilder& RecvInitialMetadata(IncomingMetadata& md) { + ops_.emplace_back(md.MakeOp()); + return *this; + } + + // Add a GRPC_OP_RECV_MESSAGE op. + BatchBuilder& RecvMessage(IncomingMessage& msg) { + ops_.emplace_back(msg.MakeOp()); + return *this; + } + + // Add a GRPC_OP_RECV_STATUS_ON_CLIENT op. + BatchBuilder& RecvStatusOnClient(IncomingStatusOnClient& status) { + ops_.emplace_back(status.MakeOp()); + return *this; + } + + // Add a GRPC_OP_RECV_CLOSE_ON_SERVER op. + BatchBuilder& RecvCloseOnServer(IncomingCloseOnServer& close) { + ops_.emplace_back(close.MakeOp()); + return *this; + } + + private: + // We need to track little bits of memory up until the batch is executed. + // One Thing is one such block of memory. + // We specialize it with SpecificThing to track a specific type of memory. + // These get placed on things_ and deleted when the batch is executed. + class Thing { + public: + virtual ~Thing() = default; + }; + template + class SpecificThing final : public Thing { + public: + template + explicit SpecificThing(Args&&... args) + : t_(std::forward(args)...) {} + SpecificThing() = default; + + T& get() { return t_; } + + private: + T t_; + }; + + // Make a thing of type T, and return a reference to it. + template + T& Make(Args&&... args) { + things_.emplace_back(new SpecificThing(std::forward(args)...)); + return static_cast*>(things_.back().get())->get(); + } + + grpc_call* call_; + const int tag_; + std::vector ops_; + std::vector> things_; + }; + + // Wrapper around a grpc_call. + // Instantiated by ClientCallBuilder via NewClientCall for client calls. + // Wrapped by IncomingCall for server calls. + class Call { + public: + explicit Call(grpc_call* call) : call_(call) {} + Call(const Call&) = delete; + Call& operator=(const Call&) = delete; + Call(Call&& other) noexcept : call_(std::exchange(other.call_, nullptr)) {} + ~Call() { + if (call_ != nullptr) grpc_call_unref(call_); + } + // Construct a batch with a tag - upon destruction of the BatchBuilder the + // operation will occur. + BatchBuilder NewBatch(int tag) { return BatchBuilder(call_, tag); } + // Cancel the call + void Cancel() { grpc_call_cancel(call_, nullptr); } + void CancelWithStatus(grpc_status_code status, const char* message) { + grpc_call_cancel_with_status(call_, status, message, nullptr); + } + // Access the peer structure (returns a string that can be matched, etc) - + // or nullopt if grpc_call_get_peer returns nullptr. + absl::optional GetPeer() { + char* peer = grpc_call_get_peer(call_); + if (peer == nullptr) return absl::nullopt; + std::string result(peer); + gpr_free(peer); + return result; + } + + // Set call credentials. + // Takes ownership of creds. + void SetCredentials(grpc_call_credentials* creds) { + EXPECT_EQ(grpc_call_set_credentials(call_, creds), GRPC_CALL_OK); + grpc_call_credentials_release(creds); + } + + // Retrieve the auth context. + std::unique_ptr + GetAuthContext() { + return std::unique_ptr( + grpc_call_auth_context(call_), grpc_auth_context_release); + } + + grpc_call** call_ptr() { return &call_; } + grpc_call* c_call() const { return call_; } + + private: + grpc_call* call_ = nullptr; + }; + + // Wrapper around a server call. + class IncomingCall { + public: + IncomingCall(CoreEnd2endTest& test, int tag); + IncomingCall(const IncomingCall&) = delete; + IncomingCall& operator=(const IncomingCall&) = delete; + IncomingCall(IncomingCall&&) noexcept = default; + + // Construct a batch with a tag - upon destruction of the BatchBuilder the + // operation will occur. Must have received the call first! + BatchBuilder NewBatch(int tag) { return impl_->call.NewBatch(tag); } + void Cancel() { impl_->call.Cancel(); } + + // Return the method being called. + std::string method() const { + return std::string(StringViewFromSlice(impl_->call_details.method)); + } + + // Return the host being called. + std::string host() const { + return std::string(StringViewFromSlice(impl_->call_details.host)); + } + + // Return some initial metadata. + absl::optional GetInitialMetadata(absl::string_view key) const; + + // Return the peer address. + absl::optional GetPeer() { return impl_->call.GetPeer(); } + + // Return the auth context. + std::unique_ptr + GetAuthContext() { + return impl_->call.GetAuthContext(); + } + + // Return the underlying C call object + grpc_call* c_call() { return impl_->call.c_call(); } + + // Return the encodings accepted by the peer. + BitSet GetEncodingsAcceptedByPeer() { + return BitSet::FromInt( + grpc_call_test_only_get_encodings_accepted_by_peer(c_call())); + } + + private: + struct Impl { + Impl() { + grpc_call_details_init(&call_details); + grpc_metadata_array_init(&request_metadata); + } + ~Impl() { + grpc_call_details_destroy(&call_details); + grpc_metadata_array_destroy(&request_metadata); + } + Call call{nullptr}; + grpc_call_details call_details; + grpc_metadata_array request_metadata; + }; + std::unique_ptr impl_; + }; + + // Begin construction of a client call. + ClientCallBuilder NewClientCall(std::string method) { + return ClientCallBuilder(*this, std::move(method)); + } + ClientCallBuilder NewClientCall(RegisteredCall registered_method) { + return ClientCallBuilder(*this, registered_method); + } + // Request a call on the server - notifies `tag` when complete. + IncomingCall RequestCall(int tag) { return IncomingCall(*this, tag); } + + // Pull in CqVerifier types for ergonomics + // TODO(ctiller): evaluate just dropping CqVerifier and folding it in here. + using ExpectedResult = CqVerifier::ExpectedResult; + using Maybe = CqVerifier::Maybe; + using PerformAction = CqVerifier::PerformAction; + using MaybePerformAction = CqVerifier::MaybePerformAction; + using AnyStatus = CqVerifier::AnyStatus; + // Expect a tag with some result. + void Expect(int tag, ExpectedResult result, SourceLocation whence = {}) { + expectations_++; + cq_verifier().Expect(CqVerifier::tag(tag), result, whence); + } + // Step the system until expectations are met or until timeout is reached. + // If there are no expectations logged, then step for 1 second and verify that + // no events occur. + void Step(absl::optional timeout = absl::nullopt, + SourceLocation whence = {}) { + if (expectations_ == 0) { + cq_verifier().VerifyEmpty(timeout.value_or(Duration::Seconds(1)), whence); + return; + } + expectations_ = 0; + cq_verifier().Verify(timeout.value_or(Duration::Seconds(10)), whence); + } + + // Initialize the client. + // If called, then InitServer must be called to create a server (otherwise one + // will be provided). + void InitClient(const ChannelArgs& args) { + initialized_ = true; + fixture().InitClient(args); + } + // Initialize the server. + // If called, then InitClient must be called to create a client (otherwise one + // will be provided). + void InitServer(const ChannelArgs& args) { + initialized_ = true; + fixture().InitServer(args); + } + // Remove the client. + void ShutdownAndDestroyClient() { fixture().ShutdownClient(); } + // Shutdown the server; notify tag on completion. + void ShutdownServerAndNotify(int tag) { + grpc_server_shutdown_and_notify(fixture().server(), fixture().cq(), + CqVerifier::tag(tag)); + } + // Destroy the server. + void DestroyServer() { fixture().DestroyServer(); } + // Shutdown then destroy the server. + void ShutdownAndDestroyServer() { fixture().ShutdownServer(); } + // Cancel any calls on the server. + void CancelAllCallsOnServer() { + grpc_server_cancel_all_calls(fixture().server()); + } + // Ping the server from the client + void PingServerFromClient(int tag) { + grpc_channel_ping(fixture().client(), fixture().cq(), CqVerifier::tag(tag), + nullptr); + } + // Register a call on the client, return its handle. + RegisteredCall RegisterCallOnClient(const char* method, const char* host) { + ForceInitialized(); + return RegisteredCall{ + grpc_channel_register_call(fixture().client(), method, host, nullptr)}; + } + + // Return the current connectivity state of the client. + grpc_connectivity_state CheckConnectivityState(bool try_to_connect) { + return grpc_channel_check_connectivity_state(fixture().client(), + try_to_connect); + } + + // Watch the connectivity state of the client. + void WatchConnectivityState(grpc_connectivity_state last_observed_state, + Duration deadline, int tag) { + grpc_channel_watch_connectivity_state( + fixture().client(), last_observed_state, + grpc_timeout_milliseconds_to_deadline(deadline.millis()), + fixture().cq(), CqVerifier::tag(tag)); + } + + // Return the client channel. + grpc_channel* client() { + ForceInitialized(); + return fixture().client(); + } + + // Return the server channel. + grpc_server* server() { + ForceInitialized(); + return fixture().server(); + } + + // Given a duration, return a timestamp that is that duration in the future - + // with dilation according to test environment (eg sanitizers) + Timestamp TimestampAfterDuration(Duration duration) { + return Timestamp::FromTimespecRoundUp( + grpc_timeout_milliseconds_to_deadline(duration.millis())); + } + + private: + void ForceInitialized(); + + CoreTestFixture& fixture() { + if (fixture_ == nullptr) { + grpc_init(); + fixture_ = GetParam()->create_fixture(ChannelArgs(), ChannelArgs()); + } + return *fixture_; + } + + CqVerifier& cq_verifier() { + if (cq_verifier_ == nullptr) { + cq_verifier_ = absl::make_unique( + fixture().cq(), CqVerifier::FailUsingGtestFail); + } + return *cq_verifier_; + } + + std::unique_ptr fixture_; + std::unique_ptr cq_verifier_; + int expectations_ = 0; + bool initialized_ = false; +}; + +// Define names for additional test suites. +// These make no changes to the actual class, but define new names to register +// tests against. Each new name gets a differing set of configurations in +// end2end_test_main.cc to customize the set of fixtures the tests run against. + +// Test suite for tests that rely on a secure transport +class SecureEnd2endTest : public CoreEnd2endTest {}; +// Test suite for tests that send rather large messages/metadata +class CoreLargeSendTest : public CoreEnd2endTest {}; +// Test suite for tests that need a client channel +class CoreClientChannelTest : public CoreEnd2endTest {}; +// Test suite for tests that require deadline handling +class CoreDeadlineTest : public CoreEnd2endTest {}; +// Test suite for http2 tests that only work over a single hop (unproxyable) +class Http2SingleHopTest : public CoreEnd2endTest {}; +// Test suite for tests that require retry features +class RetryTest : public CoreEnd2endTest {}; +// Test suite for write buffering +class WriteBufferingTest : public CoreEnd2endTest {}; +// Test suite for http2 tests +class Http2Test : public CoreEnd2endTest {}; +// Test suite for http2 tests that require retry features +class RetryHttp2Test : public CoreEnd2endTest {}; +// Test suite for tests that require resource quota +class ResourceQuotaTest : public CoreEnd2endTest {}; +// Test suite for tests that require a transport that supports secure call +// credentials +class PerCallCredsTest : public CoreEnd2endTest {}; +// Test suite for tests that require a transport that supports insecure call +// credentials +class PerCallCredsOnInsecureTest : public CoreEnd2endTest {}; +// Test suite for tests that verify lack of logging in particular situations +class NoLoggingTest : public CoreEnd2endTest {}; +// Test suite for tests that verify proxy authentication +class ProxyAuthTest : public CoreEnd2endTest {}; -const char* get_host_override_string(const char* str, - const CoreTestConfiguration& config); -// Returns a pointer to a statically allocated slice: future invocations -// overwrite past invocations, not threadsafe, etc... -const grpc_slice* get_host_override_slice(const char* str, - const CoreTestConfiguration& config); +} // namespace grpc_core -void validate_host_override_string(const char* pattern, grpc_slice str, - const CoreTestConfiguration& config); +// If this test fixture is being run under minstack, skip the test. +#define SKIP_IF_MINSTACK() \ + if (GetParam()->feature_mask & FEATURE_MASK_IS_MINSTACK) \ + GTEST_SKIP() << "Skipping test for minstack" #endif // GRPC_TEST_CORE_END2END_END2END_TESTS_H diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc deleted file mode 100644 index fc8ec35695f..00000000000 --- a/test/core/end2end/fixtures/h2_census.cc +++ /dev/null @@ -1,87 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/host_port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -class CensusFixture : public CoreTestFixture { - private: - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - grpc_server_credentials* server_creds = - grpc_insecure_server_credentials_create(); - auto* server = grpc_server_create( - args.Set(GRPC_ARG_ENABLE_CENSUS, true).ToC().get(), nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - GPR_ASSERT( - grpc_server_add_http2_port(server, localaddr_.c_str(), server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(server); - return server; - } - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - auto* creds = grpc_insecure_credentials_create(); - auto* client = - grpc_channel_create(localaddr_.c_str(), creds, - args.Set(GRPC_ARG_ENABLE_CENSUS, true).ToC().get()); - grpc_channel_credentials_release(creds); - return client; - } - const std::string localaddr_ = - grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die()); -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack+census", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc deleted file mode 100644 index 8cf05e5831e..00000000000 --- a/test/core/end2end/fixtures/h2_compress.cc +++ /dev/null @@ -1,96 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/host_port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -class CompressionFixture : public CoreTestFixture { - private: - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - auto* server = grpc_server_create( - args.SetIfUnset(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - GRPC_COMPRESS_GZIP) - .ToC() - .get(), - nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - grpc_server_credentials* server_creds = - grpc_insecure_server_credentials_create(); - GPR_ASSERT( - grpc_server_add_http2_port(server, localaddr_.c_str(), server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(server); - return server; - } - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - auto* client = grpc_channel_create( - localaddr_.c_str(), creds, - args.SetIfUnset(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - GRPC_COMPRESS_GZIP) - .ToC() - .get()); - grpc_channel_credentials_release(creds); - return client; - } - - std::string localaddr_ = - grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die()); -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_compression", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc deleted file mode 100644 index 5571fc8748b..00000000000 --- a/test/core/end2end/fixtures/h2_fakesec.cc +++ /dev/null @@ -1,89 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/security/credentials/fake/fake_credentials.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/, - const grpc_metadata* /*md*/, - size_t /*md_count*/, - grpc_process_auth_metadata_done_cb cb, - void* user_data) { - GPR_ASSERT(state == nullptr); - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); -} - -class FakesecFixture : public SecureFixture { - private: - grpc_channel_credentials* MakeClientCreds( - const grpc_core::ChannelArgs&) override { - return grpc_fake_transport_security_credentials_create(); - } - grpc_server_credentials* MakeServerCreds( - const grpc_core::ChannelArgs& args) override { - grpc_server_credentials* fake_ts_creds = - grpc_fake_transport_security_server_credentials_create(); - if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { - grpc_auth_metadata_processor processor = {process_auth_failure, nullptr, - nullptr}; - grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds, - processor); - } - return fake_ts_creds; - } -}; - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/fake_secure_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE, - nullptr, [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc deleted file mode 100644 index 396d90b1b67..00000000000 --- a/test/core/end2end/fixtures/h2_fd.cc +++ /dev/null @@ -1,111 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include "absl/status/status.h" - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/port.h" - -// This test won't work except with posix sockets enabled -#ifdef GRPC_POSIX_SOCKET - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/socket_utils_posix.h" -#include "src/core/lib/iomgr/unix_sockets_posix.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static void create_sockets(int sv[2]) { - int flags; - grpc_create_socketpair_if_unix(sv); - flags = fcntl(sv[0], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[0], F_SETFL, flags | O_NONBLOCK) == 0); - flags = fcntl(sv[1], F_GETFL, 0); - GPR_ASSERT(fcntl(sv[1], F_SETFL, flags | O_NONBLOCK) == 0); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[0]) == absl::OkStatus()); - GPR_ASSERT(grpc_set_socket_no_sigpipe_if_possible(sv[1]) == absl::OkStatus()); -} - -class FdFixture : public CoreTestFixture { - public: - FdFixture() { create_sockets(fd_pair_); } - - private: - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - grpc_core::ExecCtx exec_ctx; - auto* server = grpc_server_create(args.ToC().get(), nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - grpc_server_start(server); - grpc_server_credentials* creds = grpc_insecure_server_credentials_create(); - grpc_server_add_channel_from_fd(server, fd_pair_[1], creds); - grpc_server_credentials_release(creds); - return server; - } - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - grpc_core::ExecCtx exec_ctx; - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - auto* client = grpc_channel_create_from_fd("fixture_client", fd_pair_[0], - creds, args.ToC().get()); - grpc_channel_credentials_release(creds); - return client; - } - - int fd_pair_[2]; -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} - -#else // GRPC_POSIX_SOCKET - -int main(int /* argc */, char** /* argv */) { return 1; } - -#endif // GRPC_POSIX_SOCKET diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc deleted file mode 100644 index 4a2e5cecfe9..00000000000 --- a/test/core/end2end/fixtures/h2_full+pipe.cc +++ /dev/null @@ -1,72 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/port.h" - -// This test requires posix wakeup fds -#ifdef GRPC_POSIX_WAKEUP_FD - -#include - -#include "src/core/lib/iomgr/wakeup_fd_posix.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc_allow_specialized_wakeup_fd = 0; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} - -#else // GRPC_POSIX_WAKEUP_FD - -int main(int argc, char** argv) { return 1; } - -#endif // GRPC_POSIX_WAKEUP_FD diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc deleted file mode 100644 index 8c37b7ae2f3..00000000000 --- a/test/core/end2end/fixtures/h2_full+trace.cc +++ /dev/null @@ -1,95 +0,0 @@ -// -// -// Copyright 2015 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 - -#include "absl/types/optional.h" - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/port.h" // IWYU pragma: keep - -#ifdef GRPC_POSIX_SOCKET -#include -#endif - -#include -#include -#include - -#include - -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - // force tracing on, with a value to force many - // code paths in trace.c to be taken - grpc_core::ConfigVars::Overrides overrides; - overrides.trace = "doesnt-exist,http,all"; - grpc_core::ConfigVars::SetOverrides(overrides); - -#ifdef GRPC_POSIX_SOCKET - g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; -#else - g_fixture_slowdown_factor = 10; -#endif - -#ifdef GPR_WINDOWS - // on Windows, writing logs to stderr is very slow - // when stderr is redirected to a disk file. - // The "trace" tests fixtures generates large amount - // of logs, so setting a buffer for stderr prevents certain - // test cases from timing out. - setvbuf(stderr, NULL, _IOLBF, 1024); -#endif - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc deleted file mode 100644 index 89753647dba..00000000000 --- a/test/core/end2end/fixtures/h2_full.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_full_no_retry.cc b/test/core/end2end/fixtures/h2_full_no_retry.cc deleted file mode 100644 index e3e361e95c9..00000000000 --- a/test/core/end2end/fixtures/h2_full_no_retry.cc +++ /dev/null @@ -1,66 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -class NoRetryFixture : public InsecureFixture { - private: - grpc_core::ChannelArgs MutateClientArgs( - grpc_core::ChannelArgs args) override { - return args.Set(GRPC_ARG_ENABLE_RETRIES, false); - } -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - return std::make_unique(); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc deleted file mode 100644 index ebd01a5b9a8..00000000000 --- a/test/core/end2end/fixtures/h2_http_proxy.cc +++ /dev/null @@ -1,119 +0,0 @@ -// -// -// Copyright 2016 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 - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" -#include "absl/types/optional.h" - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/host_port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/http_proxy_fixture.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -class HttpProxyFilter : public CoreTestFixture { - public: - explicit HttpProxyFilter(const grpc_core::ChannelArgs& client_args) - : proxy_(grpc_end2end_http_proxy_create(client_args.ToC().get())) {} - ~HttpProxyFilter() override { - // Need to shut down the proxy users before closing the proxy (otherwise we - // become stuck). - ShutdownClient(); - ShutdownServer(); - grpc_end2end_http_proxy_destroy(proxy_); - } - - private: - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - auto* server = grpc_server_create(args.ToC().get(), nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - grpc_server_credentials* server_creds = - grpc_insecure_server_credentials_create(); - GPR_ASSERT( - grpc_server_add_http2_port(server, server_addr_.c_str(), server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(server); - return server; - } - - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - // If testing for proxy auth, add credentials to proxy uri - absl::optional proxy_auth_str = - args.GetOwnedString(GRPC_ARG_HTTP_PROXY_AUTH_CREDS); - std::string proxy_uri; - if (!proxy_auth_str.has_value()) { - proxy_uri = absl::StrFormat( - "http://%s", grpc_end2end_http_proxy_get_proxy_name(proxy_)); - } else { - proxy_uri = - absl::StrFormat("http://%s@%s", proxy_auth_str->c_str(), - grpc_end2end_http_proxy_get_proxy_name(proxy_)); - } - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - auto* client = grpc_channel_create( - server_addr_.c_str(), creds, - args.Set(GRPC_ARG_HTTP_PROXY, proxy_uri).ToC().get()); - grpc_channel_credentials_release(creds); - GPR_ASSERT(client); - return client; - } - - std::string server_addr_ = - grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die()); - grpc_end2end_http_proxy* proxy_; -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs&) { - return std::make_unique(client_args); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_insecure.cc b/test/core/end2end/fixtures/h2_insecure.cc deleted file mode 100644 index 02506838893..00000000000 --- a/test/core/end2end/fixtures/h2_insecure.cc +++ /dev/null @@ -1,84 +0,0 @@ -// -// -// Copyright 2020 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// - -#include - -#include -#include - -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -namespace { - -void ProcessAuthFailure(void* state, grpc_auth_context* /*ctx*/, - const grpc_metadata* /*md*/, size_t /*md_count*/, - grpc_process_auth_metadata_done_cb cb, - void* user_data) { - GPR_ASSERT(state == nullptr); - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); -} - -class InsecureCredsFixture : public InsecureFixture { - private: - grpc_server_credentials* MakeServerCreds( - const grpc_core::ChannelArgs& args) override { - auto* creds = grpc_insecure_server_credentials_create(); - if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { - grpc_auth_metadata_processor processor = {ProcessAuthFailure, nullptr, - nullptr}; - grpc_server_credentials_set_auth_metadata_processor(creds, processor); - } - return creds; - } -}; - -// All test configurations -CoreTestConfiguration configs[] = { - {"chttp2/insecure_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }}, -}; - -} // namespace - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_local_abstract_uds_percent_encoded.cc b/test/core/end2end/fixtures/h2_local_abstract_uds_percent_encoded.cc deleted file mode 100644 index ee760f68cab..00000000000 --- a/test/core/end2end/fixtures/h2_local_abstract_uds_percent_encoded.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2021 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 -#include - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/local_util.h" -#include "test/core/util/test_config.h" - -static std::atomic unique{0}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_local_abstract_uds_percent_encoded", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - return std::make_unique( - absl::StrFormat("unix-abstract:grpc_fullstack_test.%%00.%d.%" PRId64 - ".%" PRId32 ".%d", - getpid(), now.tv_sec, now.tv_nsec, - unique.fetch_add(1, std::memory_order_relaxed)), - UDS); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_local_ipv4.cc b/test/core/end2end/fixtures/h2_local_ipv4.cc deleted file mode 100644 index 2dcb1ddec1b..00000000000 --- a/test/core/end2end/fixtures/h2_local_ipv4.cc +++ /dev/null @@ -1,59 +0,0 @@ -// -// -// Copyright 2018 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 - -#include -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/host_port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/local_util.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_local_ipv4", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - int port = grpc_pick_unused_port_or_die(); - return std::make_unique( - grpc_core::JoinHostPort("127.0.0.1", port), LOCAL_TCP); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_local_ipv6.cc b/test/core/end2end/fixtures/h2_local_ipv6.cc deleted file mode 100644 index 30012345d1d..00000000000 --- a/test/core/end2end/fixtures/h2_local_ipv6.cc +++ /dev/null @@ -1,59 +0,0 @@ -// -// -// Copyright 2018 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 - -#include -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/host_port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/local_util.h" -#include "test/core/util/port.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_local_ipv6", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - int port = grpc_pick_unused_port_or_die(); - return std::make_unique( - grpc_core::JoinHostPort("[::1]", port), LOCAL_TCP); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_local_uds.cc b/test/core/end2end/fixtures/h2_local_uds.cc deleted file mode 100644 index 0ecc1ac0bbc..00000000000 --- a/test/core/end2end/fixtures/h2_local_uds.cc +++ /dev/null @@ -1,69 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/local_util.h" -#include "test/core/util/test_config.h" - -static std::atomic unique{1}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_local_uds", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); - return std::make_unique( - absl::StrFormat("unix:/tmp/grpc_fullstack_test.%d.%" PRId64 - ".%" PRId32 ".%d", - getpid(), now.tv_sec, now.tv_nsec, - unique.fetch_add(1, std::memory_order_relaxed)), - UDS); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_local_uds_percent_encoded.cc b/test/core/end2end/fixtures/h2_local_uds_percent_encoded.cc deleted file mode 100644 index cd44807c745..00000000000 --- a/test/core/end2end/fixtures/h2_local_uds_percent_encoded.cc +++ /dev/null @@ -1,69 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/local_util.h" -#include "test/core/util/test_config.h" - -static std::atomic unique{1}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_local_uds_percent_encoded", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, - nullptr, - [](const grpc_core::ChannelArgs& /*client_args*/, - const grpc_core::ChannelArgs& /*server_args*/) { - gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); - return std::make_unique( - absl::StrFormat("unix:/tmp/grpc_fullstack_test.%%25.%d.%" PRId64 - ".%" PRId32 ".%d", - getpid(), now.tv_sec, now.tv_nsec, - unique.fetch_add(1, std::memory_order_relaxed)), - UDS); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_oauth2_tls12.cc b/test/core/end2end/fixtures/h2_oauth2_tls12.cc deleted file mode 100644 index 0a0c747ff12..00000000000 --- a/test/core/end2end/fixtures/h2_oauth2_tls12.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_oauth2_common.h" -#include "test/core/util/test_config.h" - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_with_oauth2_fullstack_tls1_2", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_tls_version::TLS1_2); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_oauth2_tls13.cc b/test/core/end2end/fixtures/h2_oauth2_tls13.cc deleted file mode 100644 index 72559dd82ca..00000000000 --- a/test/core/end2end/fixtures/h2_oauth2_tls13.cc +++ /dev/null @@ -1,59 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_oauth2_common.h" -#include "test/core/util/test_config.h" - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_with_oauth2_fullstack_tls1_3", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_tls_version::TLS1_3); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc deleted file mode 100644 index 4dc7864e0ef..00000000000 --- a/test/core/end2end/fixtures/h2_proxy.cc +++ /dev/null @@ -1,113 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/proxy.h" -#include "test/core/util/test_config.h" - -class ProxyFixture : public CoreTestFixture { - public: - ProxyFixture(const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args) - : proxy_(grpc_end2end_proxy_create(&proxy_def_, client_args.ToC().get(), - server_args.ToC().get())) {} - ~ProxyFixture() override { grpc_end2end_proxy_destroy(proxy_); } - - private: - static grpc_server* CreateProxyServer(const char* port, - const grpc_channel_args* server_args) { - grpc_server* s = grpc_server_create(server_args, nullptr); - grpc_server_credentials* server_creds = - grpc_insecure_server_credentials_create(); - GPR_ASSERT(grpc_server_add_http2_port(s, port, server_creds)); - grpc_server_credentials_release(server_creds); - return s; - } - - static grpc_channel* CreateProxyClient(const char* target, - const grpc_channel_args* client_args) { - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - grpc_channel* channel = grpc_channel_create(target, creds, client_args); - grpc_channel_credentials_release(creds); - return channel; - } - - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - auto* server = grpc_server_create(args.ToC().get(), nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - grpc_server_credentials* server_creds = - grpc_insecure_server_credentials_create(); - GPR_ASSERT(grpc_server_add_http2_port( - server, grpc_end2end_proxy_get_server_port(proxy_), server_creds)); - grpc_server_credentials_release(server_creds); - grpc_server_start(server); - return server; - } - - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - auto* client = grpc_channel_create( - grpc_end2end_proxy_get_client_target(proxy_), creds, args.ToC().get()); - grpc_channel_credentials_release(creds); - GPR_ASSERT(client); - return client; - } - const grpc_end2end_proxy_def proxy_def_ = {CreateProxyServer, - CreateProxyClient}; - grpc_end2end_proxy* proxy_; -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack+proxy", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args) { - return std::make_unique(client_args, server_args); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc deleted file mode 100644 index 5180b79deaf..00000000000 --- a/test/core/end2end/fixtures/h2_sockpair+trace.cc +++ /dev/null @@ -1,86 +0,0 @@ -// -// -// Copyright 2015 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 -#include -#include - -#include "absl/types/optional.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "src/core/lib/iomgr/port.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/sockpair_fixture.h" -#include "test/core/util/test_config.h" - -#ifdef GRPC_POSIX_SOCKET -#include -#endif - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_core::ChannelArgs()); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - // force tracing on, with a value to force many - // code paths in trace.cc to be taken - grpc_core::ConfigVars::Overrides overrides; - overrides.trace = "doesnt-exist,http,all"; - grpc_core::ConfigVars::SetOverrides(overrides); - -#ifdef GRPC_POSIX_SOCKET - g_fixture_slowdown_factor = isatty(STDOUT_FILENO) ? 10 : 1; -#else - g_fixture_slowdown_factor = 10; -#endif - -#ifdef GPR_WINDOWS - // on Windows, writing logs to stderr is very slow - // when stderr is redirected to a disk file. - // The "trace" tests fixtures generates large amount - // of logs, so setting a buffer for stderr prevents certain - // test cases from timing out. - setvbuf(stderr, NULL, _IOLBF, 1024); -#endif - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - GPR_ASSERT(0 == grpc_tracer_set_enabled("also-doesnt-exist", 0)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("http", 1)); - GPR_ASSERT(1 == grpc_tracer_set_enabled("all", 1)); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc deleted file mode 100644 index f9e8b45537c..00000000000 --- a/test/core/end2end/fixtures/h2_sockpair.cc +++ /dev/null @@ -1,53 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/sockpair_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_core::ChannelArgs()); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc deleted file mode 100644 index 504460e2fe7..00000000000 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc +++ /dev/null @@ -1,59 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/sockpair_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - grpc_core::ChannelArgs() - .Set(GRPC_ARG_TCP_READ_CHUNK_SIZE, 1) - .Set(GRPC_ARG_TCP_MIN_READ_CHUNK_SIZE, 1) - .Set(GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE, 1)); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - g_fixture_slowdown_factor = 2; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_sockpair_with_minstack.cc b/test/core/end2end/fixtures/h2_sockpair_with_minstack.cc deleted file mode 100644 index a70d2aff383..00000000000 --- a/test/core/end2end/fixtures/h2_sockpair_with_minstack.cc +++ /dev/null @@ -1,72 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/sockpair_fixture.h" -#include "test/core/util/test_config.h" - -class SockpairWithMinstackFixture : public SockpairFixture { - public: - using SockpairFixture::SockpairFixture; - - private: - grpc_core::ChannelArgs MutateClientArgs( - grpc_core::ChannelArgs args) override { - return args.Set(GRPC_ARG_MINIMAL_STACK, true); - } - grpc_core::ChannelArgs MutateServerArgs( - grpc_core::ChannelArgs args) override { - return args.Set(GRPC_ARG_MINIMAL_STACK, true); - } -}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/socketpair+minstack", - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - grpc_core::ChannelArgs()); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_cred_reload_tls12.cc b/test/core/end2end/fixtures/h2_ssl_cred_reload_tls12.cc deleted file mode 100644 index 9e9bb87bcdf..00000000000 --- a/test/core/end2end/fixtures/h2_ssl_cred_reload_tls12.cc +++ /dev/null @@ -1,68 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include "absl/types/optional.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack_tls1_2", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(TLS1_2); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = SslCredReloadFixture::CaCertPath(); - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_cred_reload_tls13.cc b/test/core/end2end/fixtures/h2_ssl_cred_reload_tls13.cc deleted file mode 100644 index d2ee2ba7f3d..00000000000 --- a/test/core/end2end/fixtures/h2_ssl_cred_reload_tls13.cc +++ /dev/null @@ -1,68 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include "absl/types/optional.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_ssl_cred_reload_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack_tls1_3", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(TLS1_3); - }}}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = SslCredReloadFixture::CaCertPath(); - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc deleted file mode 100644 index b7a3866ef9b..00000000000 --- a/test/core/end2end/fixtures/h2_ssl_proxy.cc +++ /dev/null @@ -1,188 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include "absl/types/optional.h" - -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/iomgr/load_file.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/proxy.h" -#include "test/core/util/test_config.h" - -#define CA_CERT_PATH "src/core/tsi/test_creds/ca.pem" -#define SERVER_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SERVER_KEY_PATH "src/core/tsi/test_creds/server1.key" - -static void process_auth_failure(void* state, grpc_auth_context* /*ctx*/, - const grpc_metadata* /*md*/, - size_t /*md_count*/, - grpc_process_auth_metadata_done_cb cb, - void* user_data) { - GPR_ASSERT(state == nullptr); - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); -} - -class SslProxyFixture : public CoreTestFixture { - public: - SslProxyFixture(const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args) - : proxy_(grpc_end2end_proxy_create(&proxy_def_, client_args.ToC().get(), - server_args.ToC().get())) {} - ~SslProxyFixture() override { grpc_end2end_proxy_destroy(proxy_); } - - private: - static grpc_server* CreateProxyServer(const char* port, - const grpc_channel_args* server_args) { - grpc_server* s = grpc_server_create(server_args, nullptr); - grpc_slice cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( - nullptr, &pem_key_cert_pair, 1, 0, nullptr); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - GPR_ASSERT(grpc_server_add_http2_port(s, port, ssl_creds)); - grpc_server_credentials_release(ssl_creds); - return s; - } - - static grpc_channel* CreateProxyClient(const char* target, - const grpc_channel_args* client_args) { - grpc_channel* channel; - grpc_channel_credentials* ssl_creds = - grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); - grpc_arg ssl_name_override = { - GRPC_ARG_STRING, - const_cast(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG), - {const_cast("foo.test.google.fr")}}; - const grpc_channel_args* new_client_args = - grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); - channel = grpc_channel_create(target, ssl_creds, new_client_args); - grpc_channel_credentials_release(ssl_creds); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(new_client_args); - } - return channel; - } - - grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { - grpc_slice cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR( - "load_file", grpc_load_file(SERVER_KEY_PATH, 1, &key_slice))); - const char* server_cert = - reinterpret_cast GRPC_SLICE_START_PTR(cert_slice); - const char* server_key = - reinterpret_cast GRPC_SLICE_START_PTR(key_slice); - grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {server_key, server_cert}; - grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( - nullptr, &pem_key_cert_pair, 1, 0, nullptr); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - if (args.Contains(FAIL_AUTH_CHECK_SERVER_ARG_NAME)) { - grpc_auth_metadata_processor processor = {process_auth_failure, nullptr, - nullptr}; - grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); - } - - auto* server = grpc_server_create(args.ToC().get(), nullptr); - grpc_server_register_completion_queue(server, cq(), nullptr); - GPR_ASSERT(grpc_server_add_http2_port( - server, grpc_end2end_proxy_get_server_port(proxy_), ssl_creds)); - grpc_server_credentials_release(ssl_creds); - grpc_server_start(server); - return server; - } - - grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) override { - grpc_channel_credentials* ssl_creds = - grpc_ssl_credentials_create(nullptr, nullptr, nullptr, nullptr); - auto* client = grpc_channel_create( - grpc_end2end_proxy_get_client_target(proxy_), ssl_creds, - args.Set(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, "foo.test.google.fr") - .ToC() - .get()); - GPR_ASSERT(client != nullptr); - grpc_channel_credentials_release(ssl_creds); - return client; - } - const grpc_end2end_proxy_def proxy_def_ = {CreateProxyServer, - CreateProxyClient}; - grpc_end2end_proxy* proxy_; -}; - -// All test configurations - -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_REQUEST_PROXYING | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args) { - return std::make_unique(client_args, server_args); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = CA_CERT_PATH; - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_tls12.cc b/test/core/end2end/fixtures/h2_ssl_tls12.cc deleted file mode 100644 index 252c3145f85..00000000000 --- a/test/core/end2end/fixtures/h2_ssl_tls12.cc +++ /dev/null @@ -1,65 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include "absl/types/optional.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_ssl_tls_common.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack_tls1_2", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_tls_version::TLS1_2); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = SslTlsFixture::CaCertPath(); - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_ssl_tls13.cc b/test/core/end2end/fixtures/h2_ssl_tls13.cc deleted file mode 100644 index 73d4793d524..00000000000 --- a/test/core/end2end/fixtures/h2_ssl_tls13.cc +++ /dev/null @@ -1,65 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include -#include - -#include "absl/types/optional.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_ssl_tls_common.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/simple_ssl_fullstack_tls1_3", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER | - FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(grpc_tls_version::TLS1_3); - }}}; - -int main(int argc, char** argv) { - size_t i; - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = SslTlsFixture::CaCertPath(); - grpc_core::ConfigVars::SetOverrides(overrides); - - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_tls_certwatch_async_tls1_3.cc b/test/core/end2end/fixtures/h2_tls_certwatch_async_tls1_3.cc deleted file mode 100644 index feb6e196d6d..00000000000 --- a/test/core/end2end/fixtures/h2_tls_certwatch_async_tls1_3.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2018 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 -#include -#include - -#include "absl/types/optional.h" - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_tls_common.h" -#include "test/core/util/test_config.h" - -static CoreTestConfiguration config = { - // client: certificate watcher provider + async external verifier - // server: certificate watcher provider + async external verifier - // extra: TLS 1.3 - "chttp2/cert_watcher_provider_async_verifier_tls1_3", - kH2TLSFeatureMask, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - SecurityPrimitives::TlsVersion::V_13, - SecurityPrimitives::ProviderType::FILE_PROVIDER, - SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER); - }, -}; - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = CA_CERT_PATH; - grpc_core::ConfigVars::SetOverrides(overrides); - grpc_init(); - grpc_end2end_tests(argc, argv, config); - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_tls_certwatch_sync_tls1_2.cc b/test/core/end2end/fixtures/h2_tls_certwatch_sync_tls1_2.cc deleted file mode 100644 index e35dc1aa332..00000000000 --- a/test/core/end2end/fixtures/h2_tls_certwatch_sync_tls1_2.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2018 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 -#include -#include - -#include "absl/types/optional.h" - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_tls_common.h" -#include "test/core/util/test_config.h" - -static CoreTestConfiguration config = { - // client: certificate watcher provider + hostname verifier - // server: certificate watcher provider + sync external verifier - // extra: TLS 1.2 - "chttp2/cert_watcher_provider_sync_verifier_tls1_2", - kH2TLSFeatureMask, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - SecurityPrimitives::TlsVersion::V_12, - SecurityPrimitives::ProviderType::FILE_PROVIDER, - SecurityPrimitives::VerifierType::HOSTNAME_VERIFIER); - }, -}; - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = CA_CERT_PATH; - grpc_core::ConfigVars::SetOverrides(overrides); - grpc_init(); - grpc_end2end_tests(argc, argv, config); - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_tls_common.h b/test/core/end2end/fixtures/h2_tls_common.h index f4e38212656..8854436885f 100644 --- a/test/core/end2end/fixtures/h2_tls_common.h +++ b/test/core/end2end/fixtures/h2_tls_common.h @@ -229,9 +229,7 @@ class TlsFixture : public SecureFixture { }; static const uint32_t kH2TLSFeatureMask = - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER; + FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2; #endif // GRPC_TEST_CORE_END2END_FIXTURES_H2_TLS_COMMON_H diff --git a/test/core/end2end/fixtures/h2_tls_simple.cc b/test/core/end2end/fixtures/h2_tls_simple.cc deleted file mode 100644 index 0298fa10042..00000000000 --- a/test/core/end2end/fixtures/h2_tls_simple.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2018 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 -#include -#include - -#include "absl/types/optional.h" - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_tls_common.h" -#include "test/core/util/test_config.h" - -static CoreTestConfiguration config = { - // client: static data provider + sync external verifier - // server: static data provider + sync external verifier - // extra: TLS 1.2 - "chttp2/simple_ssl_fullstack", - kH2TLSFeatureMask, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - SecurityPrimitives::TlsVersion::V_12, - SecurityPrimitives::ProviderType::STATIC_PROVIDER, - SecurityPrimitives::VerifierType::EXTERNAL_SYNC_VERIFIER); - }, -}; - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = CA_CERT_PATH; - grpc_core::ConfigVars::SetOverrides(overrides); - grpc_init(); - grpc_end2end_tests(argc, argv, config); - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_tls_static_async_tls1_3.cc b/test/core/end2end/fixtures/h2_tls_static_async_tls1_3.cc deleted file mode 100644 index a3f12e06130..00000000000 --- a/test/core/end2end/fixtures/h2_tls_static_async_tls1_3.cc +++ /dev/null @@ -1,58 +0,0 @@ -// -// -// Copyright 2018 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 -#include -#include - -#include "absl/types/optional.h" - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/config/config_vars.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/h2_tls_common.h" -#include "test/core/util/test_config.h" - -static CoreTestConfiguration config = { - // client: static data provider + async external verifier - // server: static data provider + async external verifier - // extra: TLS 1.3 - "chttp2/static_provider_async_verifier_tls1_3", - kH2TLSFeatureMask, - "foo.test.google.fr", - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique( - SecurityPrimitives::TlsVersion::V_13, - SecurityPrimitives::ProviderType::STATIC_PROVIDER, - SecurityPrimitives::VerifierType::EXTERNAL_ASYNC_VERIFIER); - }, -}; - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_core::ConfigVars::Overrides overrides; - overrides.default_ssl_roots_file_path = CA_CERT_PATH; - grpc_core::ConfigVars::SetOverrides(overrides); - grpc_init(); - grpc_end2end_tests(argc, argv, config); - grpc_shutdown(); - return 0; -} diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc deleted file mode 100644 index 0c49dd68eef..00000000000 --- a/test/core/end2end/fixtures/h2_uds.cc +++ /dev/null @@ -1,69 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -static std::atomic unique{1}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_uds", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); - return std::make_unique(absl::StrFormat( - "unix:/tmp/grpc_fullstack_test.%d.%" PRId64 ".%" PRId32 ".%d", - getpid(), now.tv_sec, now.tv_nsec, - unique.fetch_add(1, std::memory_order_relaxed))); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/h2_uds_abstract.cc b/test/core/end2end/fixtures/h2_uds_abstract.cc deleted file mode 100644 index 62d066af114..00000000000 --- a/test/core/end2end/fixtures/h2_uds_abstract.cc +++ /dev/null @@ -1,69 +0,0 @@ -// -// -// Copyright 2015 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 -#include - -#include -#include -#include -#include - -#include "absl/strings/str_format.h" - -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/secure_fixture.h" -#include "test/core/util/test_config.h" - -static std::atomic unique{1}; - -// All test configurations -static CoreTestConfiguration configs[] = { - {"chttp2/fullstack_uds_abstract_namespace", - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | - FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); - return std::make_unique(absl::StrFormat( - "unix-abstract:grpc_fullstack_test.%d.%" PRId64 ".%" PRId32 ".%d", - getpid(), now.tv_sec, now.tv_nsec, - unique.fetch_add(1, std::memory_order_relaxed))); - }}, -}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc deleted file mode 100644 index e17873d1676..00000000000 --- a/test/core/end2end/fixtures/inproc.cc +++ /dev/null @@ -1,55 +0,0 @@ -// -// -// Copyright 2017 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 - -#include -#include - -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/fixtures/inproc_fixture.h" -#include "test/core/util/test_config.h" - -// All test configurations -static CoreTestConfiguration configs[] = {{ - "inproc", - FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, - nullptr, - [](const grpc_core::ChannelArgs&, const grpc_core::ChannelArgs&) { - return std::make_unique(); - }, -}}; - -int main(int argc, char** argv) { - size_t i; - - grpc::testing::TestEnvironment env(&argc, argv); - grpc_end2end_tests_pre_init(); - grpc_init(); - - for (i = 0; i < sizeof(configs) / sizeof(*configs); i++) { - grpc_end2end_tests(argc, argv, configs[i]); - } - - grpc_shutdown(); - - return 0; -} diff --git a/test/core/end2end/fixtures/inproc_fixture.h b/test/core/end2end/fixtures/inproc_fixture.h index 4acdcdd7a7c..8cd38d43526 100644 --- a/test/core/end2end/fixtures/inproc_fixture.h +++ b/test/core/end2end/fixtures/inproc_fixture.h @@ -21,7 +21,7 @@ #include "src/core/lib/channel/channel_args.h" #include "test/core/end2end/end2end_tests.h" -class InprocFixture : public CoreTestFixture { +class InprocFixture : public grpc_core::CoreTestFixture { private: grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { auto* server = grpc_server_create(args.ToC().get(), nullptr); diff --git a/test/core/end2end/fixtures/local_util.h b/test/core/end2end/fixtures/local_util.h index 05a89e51c63..3077b50b2a1 100644 --- a/test/core/end2end/fixtures/local_util.h +++ b/test/core/end2end/fixtures/local_util.h @@ -27,7 +27,7 @@ #include "src/core/lib/channel/channel_args.h" #include "test/core/end2end/end2end_tests.h" -class LocalTestFixture final : public CoreTestFixture { +class LocalTestFixture final : public grpc_core::CoreTestFixture { public: LocalTestFixture(std::string localaddr, grpc_local_connect_type type); diff --git a/test/core/end2end/fixtures/secure_fixture.h b/test/core/end2end/fixtures/secure_fixture.h index a64f5634f48..35745e0fff5 100644 --- a/test/core/end2end/fixtures/secure_fixture.h +++ b/test/core/end2end/fixtures/secure_fixture.h @@ -29,7 +29,7 @@ // Base class for a fixture that just needs to select cred types (or mutate // client/server channel args). -class SecureFixture : public CoreTestFixture { +class SecureFixture : public grpc_core::CoreTestFixture { public: explicit SecureFixture(std::string localaddr = grpc_core::JoinHostPort( "localhost", grpc_pick_unused_port_or_die())) diff --git a/test/core/end2end/fixtures/sockpair_fixture.h b/test/core/end2end/fixtures/sockpair_fixture.h index d1618cead0a..930974eb3f0 100644 --- a/test/core/end2end/fixtures/sockpair_fixture.h +++ b/test/core/end2end/fixtures/sockpair_fixture.h @@ -15,8 +15,11 @@ #ifndef GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H #define GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H +#include + #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "gtest/gtest.h" #include #include @@ -40,32 +43,44 @@ #include "src/core/lib/transport/transport_fwd.h" #include "test/core/end2end/end2end_tests.h" +namespace grpc_core { + class SockpairFixture : public CoreTestFixture { public: - explicit SockpairFixture(const grpc_core::ChannelArgs& ep_args) + explicit SockpairFixture(const ChannelArgs& ep_args) : ep_(grpc_iomgr_create_endpoint_pair("fixture", ep_args.ToC().get())) {} - private: - virtual grpc_core::ChannelArgs MutateClientArgs(grpc_core::ChannelArgs args) { - return args; - } - virtual grpc_core::ChannelArgs MutateServerArgs(grpc_core::ChannelArgs args) { - return args; + ~SockpairFixture() override { + ExecCtx exec_ctx; + if (ep_.client != nullptr) { + grpc_endpoint_shutdown(ep_.client, absl::InternalError("done")); + grpc_endpoint_destroy(ep_.client); + } + if (ep_.server != nullptr) { + grpc_endpoint_shutdown(ep_.server, absl::InternalError("done")); + grpc_endpoint_destroy(ep_.server); + } } - grpc_server* MakeServer(const grpc_core::ChannelArgs& in_args) override { + + private: + virtual ChannelArgs MutateClientArgs(ChannelArgs args) { return args; } + virtual ChannelArgs MutateServerArgs(ChannelArgs args) { return args; } + grpc_server* MakeServer(const ChannelArgs& in_args) override { auto args = MutateServerArgs(in_args); - grpc_core::ExecCtx exec_ctx; + ExecCtx exec_ctx; grpc_transport* transport; auto* server = grpc_server_create(args.ToC().get(), nullptr); grpc_server_register_completion_queue(server, cq(), nullptr); grpc_server_start(server); - auto server_channel_args = grpc_core::CoreConfiguration::Get() + auto server_channel_args = CoreConfiguration::Get() .channel_args_preconditioning() .PreconditionChannelArgs(args.ToC().get()); - transport = - grpc_create_chttp2_transport(server_channel_args, ep_.server, false); - grpc_endpoint_add_to_pollset(ep_.server, grpc_cq_pollset(cq())); - grpc_core::Server* core_server = grpc_core::Server::FromC(server); + auto* server_endpoint = std::exchange(ep_.server, nullptr); + EXPECT_NE(server_endpoint, nullptr); + transport = grpc_create_chttp2_transport(server_channel_args, + server_endpoint, false); + grpc_endpoint_add_to_pollset(server_endpoint, grpc_cq_pollset(cq())); + Server* core_server = Server::FromC(server); grpc_error_handle error = core_server->SetupTransport( transport, nullptr, core_server->channel_args(), nullptr); if (error.ok()) { @@ -75,9 +90,9 @@ class SockpairFixture : public CoreTestFixture { } return server; } - grpc_channel* MakeClient(const grpc_core::ChannelArgs& in_args) override { - grpc_core::ExecCtx exec_ctx; - auto args = grpc_core::CoreConfiguration::Get() + grpc_channel* MakeClient(const ChannelArgs& in_args) override { + ExecCtx exec_ctx; + auto args = CoreConfiguration::Get() .channel_args_preconditioning() .PreconditionChannelArgs( MutateClientArgs(in_args) @@ -85,9 +100,11 @@ class SockpairFixture : public CoreTestFixture { .ToC() .get()); grpc_transport* transport; - transport = grpc_create_chttp2_transport(args, ep_.client, true); - auto channel = grpc_core::Channel::Create( - "socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport); + auto* client_endpoint = std::exchange(ep_.client, nullptr); + EXPECT_NE(client_endpoint, nullptr); + transport = grpc_create_chttp2_transport(args, client_endpoint, true); + auto channel = Channel::Create("socketpair-target", args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); grpc_channel* client; if (channel.ok()) { client = channel->release()->c_ptr(); @@ -104,5 +121,6 @@ class SockpairFixture : public CoreTestFixture { grpc_endpoint_pair ep_; }; +} // namespace grpc_core #endif // GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py deleted file mode 100755 index 4d004b96b91..00000000000 --- a/test/core/end2end/gen_build_yaml.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2015 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. -"""Generates the list of end2end test cases from generate_tests.bzl""" - -import os -import sys - -import yaml - -_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..')) -os.chdir(_ROOT) - - -def load(*args): - """Replacement of bazel's load() function""" - pass - - -def struct(**kwargs): - return kwargs # all the args as a dict - - -# generate_tests.bzl is now the source of truth for end2end tests. -# The .bzl file is basically a python file and we can "execute" it -# to get access to the variables it defines. -exec( - compile( - open('test/core/end2end/generate_tests.bzl', "rb").read(), - 'test/core/end2end/generate_tests.bzl', 'exec')) - - -def main(): - json = { - # needed by end2end_tests.cc.template - 'core_end2end_tests': - dict((t, END2END_TESTS[t]['secure']) for t in END2END_TESTS.keys()) - } - print(yaml.dump(json)) - - -if __name__ == '__main__': - main() diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl deleted file mode 100755 index 1a5cab9aeb3..00000000000 --- a/test/core/end2end/generate_tests.bzl +++ /dev/null @@ -1,499 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2015 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. -"""Generates the appropriate build.json data for all the end2end tests.""" - -load( - "//bazel:grpc_build_system.bzl", - "grpc_cc_binary", - "grpc_cc_library", - "grpc_sh_test", -) -load("flaky.bzl", "FLAKY_TESTS") - -def _fixture_options( - fullstack = True, - includes_proxy = False, - dns_resolver = True, - name_resolution = True, - secure = True, - tracing = False, - _platforms = ["windows", "linux", "mac", "posix"], - is_inproc = False, - is_1byte = False, - is_http2 = True, - is_minstack = False, - supports_proxy_auth = False, - supports_write_buffering = True, - client_channel = True, - supports_msvc = True, - supports_retry = None, - tags = []): - if supports_retry == None: - supports_retry = client_channel - return struct( - fullstack = fullstack, - includes_proxy = includes_proxy, - dns_resolver = dns_resolver, - name_resolution = name_resolution, - secure = secure, - tracing = tracing, - is_inproc = is_inproc, - is_1byte = is_1byte, - is_http2 = is_http2, - is_minstack = is_minstack, - supports_proxy_auth = supports_proxy_auth, - supports_write_buffering = supports_write_buffering, - client_channel = client_channel, - supports_msvc = supports_msvc, - _platforms = _platforms, - supports_retry = supports_retry, - tags = tags, - ) - -# maps fixture name to whether it requires the security library -END2END_FIXTURES = { - "h2_compress": _fixture_options(), - "h2_census": _fixture_options(), - # TODO(juanlishen): This is disabled for now, but should be considered to re-enable once we have - # decided how the load reporting service should be enabled. - #'h2_load_reporting': _fixture_options(), - "h2_fakesec": _fixture_options(), - "h2_fd": _fixture_options( - dns_resolver = False, - fullstack = False, - client_channel = False, - _platforms = ["linux", "mac", "posix"], - tags = ["no_test_ios"], - ), - "h2_full": _fixture_options( - tags = ["event_engine_client_test"], - ), - "h2_full_no_retry": _fixture_options(supports_retry = False), - "h2_full+pipe": _fixture_options(_platforms = ["linux"]), - "h2_full+trace": _fixture_options(tracing = True), - "h2_http_proxy": _fixture_options(supports_proxy_auth = True), - "h2_insecure": _fixture_options(secure = True), - "h2_oauth2_tls12": _fixture_options(), - "h2_oauth2_tls13": _fixture_options(), - "h2_proxy": _fixture_options(includes_proxy = True), - "h2_sockpair_1byte": _fixture_options( - fullstack = False, - dns_resolver = False, - client_channel = False, - is_1byte = True, - ), - "h2_sockpair": _fixture_options( - fullstack = False, - dns_resolver = False, - client_channel = False, - ), - "h2_sockpair_with_minstack": _fixture_options( - fullstack = False, - dns_resolver = False, - client_channel = False, - is_minstack = True, - ), - "h2_sockpair+trace": _fixture_options( - fullstack = False, - dns_resolver = False, - tracing = True, - client_channel = False, - ), - "h2_ssl_tls12": _fixture_options(secure = True), - "h2_ssl_tls13": _fixture_options(secure = True), - "h2_ssl_cred_reload_tls12": _fixture_options(secure = True), - "h2_ssl_cred_reload_tls13": _fixture_options(secure = True), - "h2_tls_simple": _fixture_options(secure = True), - "h2_tls_static_async_tls1_3": _fixture_options(secure = True), - "h2_tls_certwatch_sync_tls1_2": _fixture_options(secure = True), - "h2_tls_certwatch_async_tls1_3": _fixture_options(secure = True), - "h2_local_abstract_uds_percent_encoded": _fixture_options( - secure = True, - dns_resolver = False, - _platforms = ["linux", "posix"], - ), - "h2_local_uds": _fixture_options( - secure = True, - dns_resolver = False, - _platforms = ["linux", "mac", "posix"], - ), - "h2_local_uds_percent_encoded": _fixture_options( - secure = True, - dns_resolver = False, - _platforms = ["linux", "mac", "posix"], - ), - "h2_local_ipv4": _fixture_options( - secure = True, - dns_resolver = False, - _platforms = ["linux", "mac", "posix"], - tags = ["requires-net:ipv4", "requires-net:loopback", "event_engine_client"], - ), - "h2_local_ipv6": _fixture_options( - secure = True, - dns_resolver = False, - _platforms = ["linux", "mac", "posix"], - ), - "h2_ssl_proxy": _fixture_options(includes_proxy = True, secure = True), - "h2_uds": _fixture_options( - dns_resolver = False, - _platforms = ["linux", "mac", "posix"], - ), - "h2_uds_abstract": _fixture_options( - dns_resolver = False, - _platforms = ["linux", "posix"], - ), - "inproc": _fixture_options( - secure = True, - fullstack = False, - dns_resolver = False, - name_resolution = False, - is_inproc = True, - is_http2 = False, - supports_write_buffering = False, - client_channel = False, - ), -} - -def _test_options( - needs_fullstack = False, - needs_dns = False, - needs_names = False, - proxyable = True, - secure = False, - traceable = False, - exclude_inproc = False, - exclude_1byte = False, - exclude_minstack = False, - needs_http2 = False, - needs_proxy_auth = False, - needs_write_buffering = False, - needs_client_channel = False, - needs_retry = False, - short_name = None, - tags = [], - exclude_pollers = []): - return struct( - needs_fullstack = needs_fullstack, - needs_dns = needs_dns, - needs_names = needs_names, - proxyable = proxyable, - secure = secure, - traceable = traceable, - exclude_inproc = exclude_inproc, - exclude_1byte = exclude_1byte, - exclude_minstack = exclude_minstack, - needs_http2 = needs_http2, - needs_proxy_auth = needs_proxy_auth, - needs_write_buffering = needs_write_buffering, - needs_client_channel = needs_client_channel, - needs_retry = needs_retry, - short_name = short_name, - tags = tags, - exclude_pollers = exclude_pollers, - ) - -# maps test names to options -END2END_TESTS = { - "bad_hostname": _test_options(needs_names = True), - "bad_ping": _test_options(needs_fullstack = True, proxyable = False), - "binary_metadata": _test_options(), - "resource_quota_server": _test_options( - proxyable = False, - # TODO(b/151212019): Test case known to be flaky under epoll1. - exclude_pollers = ["epoll1"], - exclude_1byte = True, - ), - "call_creds": _test_options(secure = True), - "call_host_override": _test_options( - needs_fullstack = True, - needs_dns = True, - needs_names = True, - ), - "cancel_after_accept": _test_options(), - "cancel_after_client_done": _test_options(), - "cancel_after_invoke": _test_options(), - "cancel_after_round_trip": _test_options(), - "cancel_before_invoke": _test_options(), - "cancel_in_a_vacuum": _test_options(), - "cancel_with_status": _test_options(), - "client_streaming": _test_options(), - "compressed_payload": _test_options(proxyable = False, exclude_inproc = True, exclude_minstack = True), - "connectivity": _test_options( - needs_fullstack = True, - needs_names = True, - proxyable = False, - ), - "channelz": _test_options(), - "default_host": _test_options( - needs_fullstack = True, - needs_dns = True, - needs_names = True, - ), - "disappearing_server": _test_options(needs_fullstack = True, needs_names = True), - "empty_batch": _test_options(), - "filter_causes_close": _test_options(), - "filter_init_fails": _test_options(), - "filter_context": _test_options(), - "filtered_metadata": _test_options(), - "graceful_server_shutdown": _test_options(exclude_inproc = True), - "grpc_authz": _test_options(secure = True), - "hpack_size": _test_options( - proxyable = False, - traceable = False, - exclude_inproc = True, - ), - "high_initial_seqno": _test_options(), - "invoke_large_request": _test_options(exclude_1byte = True, tags = ["flow_control_test"]), - "keepalive_timeout": _test_options(proxyable = False, needs_http2 = True), - "large_metadata": _test_options(exclude_1byte = True), - "max_concurrent_streams": _test_options( - proxyable = False, - exclude_inproc = True, - exclude_minstack = True, - ), - "max_connection_age": _test_options(exclude_minstack = True, exclude_inproc = True), - "max_connection_idle": _test_options(needs_fullstack = True, proxyable = False), - "max_message_length": _test_options(exclude_minstack = True), - "negative_deadline": _test_options(exclude_minstack = True), - "no_logging": _test_options(traceable = False), - "no_op": _test_options(), - "payload": _test_options(exclude_1byte = True), - # TODO(juanlishen): This is disabled for now because it depends on some generated functions in - # end2end_tests.cc, which are not generated because they would depend on OpenCensus while - # OpenCensus can only be built via Bazel so far. - # 'load_reporting_hook': _test_options(), - "ping_pong_streaming": _test_options(tags = ["flow_control_test"]), - "ping": _test_options(needs_fullstack = True, proxyable = False), - "proxy_auth": _test_options(needs_proxy_auth = True), - "registered_call": _test_options(), - "request_with_flags": _test_options(proxyable = False), - "request_with_payload": _test_options(), - "retry": _test_options(needs_client_channel = True, needs_retry = True), - "retry_cancellation": _test_options(needs_client_channel = True, needs_retry = True), - "retry_cancel_during_delay": _test_options(needs_client_channel = True, needs_retry = True), - "retry_cancel_with_multiple_send_batches": _test_options( - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_cancel3", - needs_client_channel = True, - needs_retry = True, - ), - "retry_cancel_after_first_attempt_starts": _test_options( - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_cancel4", - needs_client_channel = True, - needs_retry = True, - ), - "retry_disabled": _test_options(needs_client_channel = True, needs_retry = True), - "retry_exceeds_buffer_size_in_delay": _test_options(needs_client_channel = True, needs_retry = True), - "retry_exceeds_buffer_size_in_initial_batch": _test_options( - needs_client_channel = True, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_exceeds_buffer_size_in_init", - needs_retry = True, - ), - "retry_exceeds_buffer_size_in_subsequent_batch": _test_options( - needs_client_channel = True, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_exceeds_buffer_size_in_subseq", - needs_retry = True, - ), - "retry_lb_drop": _test_options(needs_client_channel = True, needs_retry = True), - "retry_lb_fail": _test_options(needs_client_channel = True, needs_retry = True), - "retry_non_retriable_status": _test_options(needs_client_channel = True, needs_retry = True), - "retry_non_retriable_status_before_recv_trailing_metadata_started": _test_options( - needs_client_channel = True, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_non_retriable_status2", - needs_retry = True, - ), - "retry_per_attempt_recv_timeout": _test_options(needs_client_channel = True, needs_retry = True), - "retry_per_attempt_recv_timeout_on_last_attempt": _test_options( - needs_client_channel = True, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_per_attempt_recv_timeout2", - needs_retry = True, - ), - "retry_recv_initial_metadata": _test_options(needs_client_channel = True, needs_retry = True), - "retry_recv_message": _test_options(needs_client_channel = True, needs_retry = True), - "retry_recv_message_replay": _test_options(needs_client_channel = True, needs_retry = True), - "retry_recv_trailing_metadata_error": _test_options(needs_client_channel = True, needs_retry = True), - "retry_send_initial_metadata_refs": _test_options(needs_client_channel = True, needs_retry = True), - "retry_send_op_fails": _test_options(needs_client_channel = True, needs_retry = True), - "retry_send_recv_batch": _test_options(needs_client_channel = True, needs_retry = True), - "retry_server_pushback_delay": _test_options(needs_client_channel = True, needs_retry = True), - "retry_server_pushback_disabled": _test_options(needs_client_channel = True, needs_retry = True), - "retry_streaming": _test_options(needs_client_channel = True, needs_retry = True), - "retry_streaming_after_commit": _test_options(needs_client_channel = True, needs_retry = True), - "retry_streaming_succeeds_before_replay_finished": _test_options( - needs_client_channel = True, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_streaming2", - needs_retry = True, - ), - "retry_throttled": _test_options(needs_client_channel = True, needs_retry = True), - "retry_too_many_attempts": _test_options(needs_client_channel = True, needs_retry = True), - "retry_transparent_goaway": _test_options(needs_client_channel = True, needs_retry = True), - "retry_transparent_not_sent_on_wire": _test_options(needs_client_channel = True, needs_retry = True), - "retry_transparent_max_concurrent_streams": _test_options( - needs_client_channel = True, - proxyable = False, - # TODO(jtattermusch): too long bazel test name makes the test flaky on Windows RBE - # See b/151617965 - short_name = "retry_transparent_mcs", - needs_retry = True, - ), - "retry_unref_before_finish": _test_options(needs_client_channel = True, needs_retry = True), - "retry_unref_before_recv": _test_options(needs_client_channel = True, needs_retry = True), - "server_finishes_request": _test_options(), - "server_streaming": _test_options(needs_http2 = True), - "shutdown_finishes_calls": _test_options(), - "shutdown_finishes_tags": _test_options(), - "simple_delayed_request": _test_options(needs_fullstack = True), - "simple_metadata": _test_options(), - "simple_request": _test_options(), - "streaming_error_response": _test_options(), - "trailing_metadata": _test_options(), - "authority_not_supported": _test_options(), - "filter_latency": _test_options(), - "filter_status_code": _test_options(), - "write_buffering": _test_options(needs_write_buffering = True), - "write_buffering_at_end": _test_options(needs_write_buffering = True), -} - -def _compatible(fopt, topt): - if topt.needs_fullstack: - if not fopt.fullstack: - return False - if topt.needs_dns: - if not fopt.dns_resolver: - return False - if topt.needs_names: - if not fopt.name_resolution: - return False - if not topt.proxyable: - if fopt.includes_proxy: - return False - if not topt.traceable: - if fopt.tracing: - return False - if topt.exclude_inproc: - if fopt.is_inproc: - return False - if topt.exclude_1byte: - if fopt.is_1byte: - return False - if topt.exclude_minstack: - if fopt.is_minstack: - return False - if topt.needs_http2: - if not fopt.is_http2: - return False - if topt.needs_proxy_auth: - if not fopt.supports_proxy_auth: - return False - if topt.needs_write_buffering: - if not fopt.supports_write_buffering: - return False - if topt.needs_client_channel: - if not fopt.client_channel: - return False - if topt.needs_retry: - if not fopt.supports_retry: - return False - return True - -def _platform_support_tags(fopt): - result = [] - if not "windows" in fopt._platforms: - result.append("no_windows") - if not "mac" in fopt._platforms: - result.append("no_mac") - if not "linux" in fopt._platforms: - result.append("no_linux") - return result - -# buildifier: disable=unnamed-macro -def grpc_end2end_tests(): - """Instantiates the gRPC end2end tests.""" - grpc_cc_library( - name = "end2end_tests", - srcs = ["end2end_tests.cc", "end2end_test_utils.cc"] + - ["tests/%s.cc" % t for t in sorted(END2END_TESTS.keys())], - hdrs = [ - "tests/cancel_test_helpers.h", - "end2end_tests.h", - ], - language = "C++", - testonly = 1, - deps = [ - ":cq_verifier", - ":ssl_test_data", - ":http_proxy", - ":proxy", - ":fixture_support", - "//test/core/util:test_lb_policies", - "//:grpc_authorization_provider", - "//:grpc_http_filters", - "//src/core:event_log", - ], - visibility = [ - "//src/objective-c/tests:__subpackages__", - ], - ) - for f, fopt in END2END_FIXTURES.items(): - bin_name = "%s_test" % f - grpc_cc_binary( - name = bin_name, - srcs = ["fixtures/%s.cc" % f, "fixtures/h2_tls_common.h"], - language = "C++", - testonly = 1, - data = [ - "//src/core/tsi/test_creds:ca.pem", - "//src/core/tsi/test_creds:server1.key", - "//src/core/tsi/test_creds:server1.pem", - ], - deps = [ - ":end2end_tests", - "//test/core/util:grpc_test_util", - "//:grpc", - "//:gpr", - "//:grpc_http_filters", - ], - tags = _platform_support_tags(fopt) + fopt.tags, - ) - for t, topt in END2END_TESTS.items(): - if not _compatible(fopt, topt): - continue - test_short_name = str(t) if not topt.short_name else topt.short_name - name = "%s_test@%s" % (f, test_short_name) - grpc_sh_test( - name = name, - srcs = ["run.sh"], - data = [":" + bin_name], - args = ["$(location %s)" % bin_name, t], - tags = _platform_support_tags(fopt) + fopt.tags + topt.tags + [ - "no_test_ios", - "core_end2end_test", - ], - flaky = name in FLAKY_TESTS, - exclude_pollers = topt.exclude_pollers, - ) diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc index de3bcc9cf1d..0f713c785ca 100644 --- a/test/core/end2end/h2_ssl_cert_test.cc +++ b/test/core/end2end/h2_ssl_cert_test.cc @@ -141,8 +141,7 @@ typedef enum { SUCCESS, FAIL } test_result; #define SSL_TEST(request_type, cert_type, result) \ { \ {TEST_NAME(request_type, cert_type, result), \ - FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | \ - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | \ + FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | \ FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL, \ "foo.test.google.fr", TestFixture::MakeFactory(request_type, cert_type)}, \ result \ @@ -150,7 +149,7 @@ typedef enum { SUCCESS, FAIL } test_result; // All test configurations struct CoreTestConfigWrapper { - CoreTestConfiguration config; + grpc_core::CoreTestConfiguration config; test_result result; }; @@ -194,7 +193,7 @@ static CoreTestConfigWrapper configs[] = { BAD_CERT_PAIR, FAIL), }; -static void simple_request_body(CoreTestFixture* f, +static void simple_request_body(grpc_core::CoreTestFixture* f, test_result expected_result) { grpc_call* c; gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); @@ -239,7 +238,7 @@ class H2SslCertTest : public ::testing::TestWithParam { } void TearDown() override { fixture_.reset(); } - std::unique_ptr fixture_; + std::unique_ptr fixture_; }; TEST_P(H2SslCertTest, SimpleRequestBody) { diff --git a/test/core/end2end/run.sh b/test/core/end2end/run.sh deleted file mode 100755 index eaad9fb41a5..00000000000 --- a/test/core/end2end/run.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# Arbitrary shell script runner -# Copyright 2017 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. -set -ex -"$@" diff --git a/test/core/end2end/tests/authority_not_supported.cc b/test/core/end2end/tests/authority_not_supported.cc deleted file mode 100644 index db34001fb03..00000000000 --- a/test/core/end2end/tests/authority_not_supported.cc +++ /dev/null @@ -1,142 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Request/response with metadata and payload. -static void test_with_authority_header(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - auto f = begin_test(config, "test_with_authority_header", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - &host, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_CANCELLED); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); -} - -void authority_not_supported(const CoreTestConfiguration& config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER) { - return; - } - test_with_authority_header(config); -} - -void authority_not_supported_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_hostname.cc b/test/core/end2end/tests/bad_hostname.cc deleted file mode 100644 index 77b24be5c57..00000000000 --- a/test/core/end2end/tests/bad_hostname.cc +++ /dev/null @@ -1,124 +0,0 @@ -// -// -// Copyright 2015 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 - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - return f; -} - -static void simple_request_body(CoreTestFixture* f) { - grpc_call* c; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - grpc_slice host = grpc_slice_from_static_string("slartibartfast.local"); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - &host, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_INTERNAL); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); -} - -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - simple_request_body(f.get()); -} - -void bad_hostname(const CoreTestConfiguration& config) { - if (config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) { - test_invoke_simple_request(config); - } -} - -void bad_hostname_pre_init(void) {} diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc index d7e7f0cebd9..19ec4bcb9ad 100644 --- a/test/core/end2end/tests/bad_ping.cc +++ b/test/core/end2end/tests/bad_ping.cc @@ -16,104 +16,41 @@ // // -#include - -#include -#include +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/time.h" -#include "src/core/lib/surface/channel.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" #define MAX_PING_STRIKES 2 -// Send more pings than server allows to trigger server's GOAWAY. -static void test_bad_ping(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_core::CqVerifier cqv(f->cq()); - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0) - .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, - grpc_core::Duration::Minutes(5).millis()) - .Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES) - .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); - - f->InitClient(client_args); - f->InitServer(server_args); - - grpc_call* c; - grpc_call* s; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); +namespace grpc_core { +namespace { +// Send more pings than server allows to trigger server's GOAWAY. +TEST_P(RetryHttp2Test, BadPing) { + InitClient(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0)); + InitServer(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, + Duration::Minutes(5).millis()) + .Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); // Send too many pings to the server to trigger the punishment: // The first ping will let server mark its last_recv time. Afterwards, each // ping will trigger a ping strike, and we need at least MAX_PING_STRIKES @@ -121,214 +58,84 @@ static void test_bad_ping(const CoreTestConfiguration& config) { // needed here. int i; for (i = 1; i <= MAX_PING_STRIKES + 2; i++) { - grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(200 + i), - nullptr); - cqv.Expect(grpc_core::CqVerifier::tag(200 + i), true); + PingServerFromClient(200 + i); + Expect(200 + i, true); if (i == MAX_PING_STRIKES + 2) { - cqv.Expect(grpc_core::CqVerifier::tag(1), true); + Expect(1, true); } - cqv.Verify(); + Step(); } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - cqv.Verify(); - - grpc_call_unref(s); - + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + ShutdownServerAndNotify(103); + Expect(103, true); + Step(); // The connection should be closed immediately after the misbehaved pings, // the in-progress RPC should fail. - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(c); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_TRUE(client_close.was_cancelled()); } // Try sending more pings than server allows, but server should be fine because // max_pings_without_data should limit pings sent out on wire. -static void test_pings_without_data(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_core::CqVerifier cqv(f->cq()); +TEST_P(RetryHttp2Test, PingsWithoutData) { // Only allow MAX_PING_STRIKES pings without data (DATA/HEADERS/WINDOW_UPDATE) // so that the transport will throttle the excess pings. - auto client_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, MAX_PING_STRIKES) - .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, - grpc_core::Duration::Minutes(5).millis()) - .Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES) - .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); - - f->InitClient(client_args); - f->InitServer(server_args); - - grpc_call* c; - grpc_call* s; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + InitClient(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, MAX_PING_STRIKES) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0)); + InitServer(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, + Duration::Minutes(5).millis()) + .Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); // Send too many pings to the server similar to the previous test case. // However, since we set the MAX_PINGS_WITHOUT_DATA at the client side, only // MAX_PING_STRIKES will actually be sent and the rpc will still succeed. int i; for (i = 1; i <= MAX_PING_STRIKES + 2; i++) { - grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(200 + i), - nullptr); + PingServerFromClient(200 + i); if (i <= MAX_PING_STRIKES) { - cqv.Expect(grpc_core::CqVerifier::tag(200 + i), true); + Expect(200 + i, true); } - cqv.Verify(); + Step(); } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); // Client call should return. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - + Expect(1, true); + Step(); + ShutdownServerAndNotify(103); + Expect(103, true); // Also expect the previously blocked pings to complete with an error - cqv.Expect(grpc_core::CqVerifier::tag(200 + MAX_PING_STRIKES + 1), false); - cqv.Expect(grpc_core::CqVerifier::tag(200 + MAX_PING_STRIKES + 2), false); - - cqv.Verify(); - - grpc_call_unref(s); - + Expect(200 + MAX_PING_STRIKES + 1, false); + Expect(200 + MAX_PING_STRIKES + 2, false); + Step(); // The rpc should be successful. - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(c); -} - -void bad_ping(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_bad_ping(config); - test_pings_without_data(config); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(s.method(), "/foo"); } -void bad_ping_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/binary_metadata.cc b/test/core/end2end/tests/binary_metadata.cc index ec21297b65f..67a7ea697c1 100644 --- a/test/core/end2end/tests/binary_metadata.cc +++ b/test/core/end2end/tests/binary_metadata.cc @@ -16,272 +16,104 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/channel_args_preconditioning.h" -#include "src/core/lib/config/core_configuration.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - client_args = - const_cast(grpc_core::CoreConfiguration::Get() - .channel_args_preconditioning() - .PreconditionChannelArgs(client_args) - .ToC() - .release()); - server_args = - const_cast(grpc_core::CoreConfiguration::Get() - .channel_args_preconditioning() - .PreconditionChannelArgs(server_args) - .ToC() - .release()); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - grpc_channel_args_destroy(client_args); - grpc_channel_args_destroy(server_args); - return f; +namespace grpc_core { + +static void BinaryMetadata(CoreEnd2endTest& test, bool server_true_binary, + bool client_true_binary) { + test.InitServer( + ChannelArgs().Set(GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, server_true_binary)); + test.InitClient( + ChannelArgs().Set(GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, client_true_binary)); + + auto key1_payload = RandomBinarySlice(32); + auto key2_payload = RandomBinarySlice(18); + auto key3_payload = RandomBinarySlice(17); + auto key4_payload = RandomBinarySlice(68); + auto key5_payload = RandomBinarySlice(33); + auto key6_payload = RandomBinarySlice(2); + auto request_payload = RandomBinarySlice(7); + auto response_payload = RandomBinarySlice(9); + auto status_string = RandomBinarySlice(256); + + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_md; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({ + {"key1-bin", key1_payload.as_string_view()}, + {"key2-bin", key2_payload.as_string_view()}, + }) + .SendMessage(request_payload.Ref()) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_md) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102) + .SendInitialMetadata({ + {"key3-bin", key3_payload.as_string_view()}, + {"key4-bin", key4_payload.as_string_view()}, + }) + .RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage(response_payload.Ref()) + .SendStatusFromServer(GRPC_STATUS_OK, status_string.as_string_view(), + { + {"key5-bin", key5_payload.as_string_view()}, + {"key6-bin", key6_payload.as_string_view()}, + }); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), status_string.as_string_view()); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), request_payload); + EXPECT_EQ(server_message.payload(), response_payload); + EXPECT_EQ(s.GetInitialMetadata("key1-bin"), key1_payload.as_string_view()); + EXPECT_EQ(s.GetInitialMetadata("key2-bin"), key2_payload.as_string_view()); + EXPECT_EQ(server_initial_md.Get("key3-bin"), key3_payload.as_string_view()); + EXPECT_EQ(server_initial_md.Get("key4-bin"), key4_payload.as_string_view()); + EXPECT_EQ(server_status.GetTrailingMetadata("key5-bin"), + key5_payload.as_string_view()); + EXPECT_EQ(server_status.GetTrailingMetadata("key6-bin"), + key6_payload.as_string_view()); } -// Request/response with metadata and payload. -static void test_request_response_with_metadata_and_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = { - {grpc_slice_from_static_string("key1-bin"), - grpc_slice_from_static_string( - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key2-bin"), - grpc_slice_from_static_string( - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - grpc_metadata meta_s[2] = { - {grpc_slice_from_static_string("key3-bin"), - grpc_slice_from_static_string( - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key4-bin"), - grpc_slice_from_static_string( - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - auto f = begin_test(config, "test_request_response_with_metadata_and_payload", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_string = grpc_slice_from_static_string( - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12" - "\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24" - "\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36" - "\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48" - "\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a" - "\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c" - "\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e" - "\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2" - "\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4" - "\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6" - "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8" - "\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea" - "\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc" - "\xfd\xfe\xff"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT( - 0 == - grpc_slice_str_cmp( - details, - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" - "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" - "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" - "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" - "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" - "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" - "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" - "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" - "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" - "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0" - "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" - "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" - "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" - "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0" - "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata( - &request_metadata_recv, "key1-bin", - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc")); - GPR_ASSERT(contains_metadata( - &request_metadata_recv, "key2-bin", - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d")); - GPR_ASSERT(contains_metadata( - &initial_metadata_recv, "key3-bin", - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee")); - GPR_ASSERT(contains_metadata( - &initial_metadata_recv, "key4-bin", - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); +TEST_P(CoreEnd2endTest, BinaryMetadataServerTrueBinaryClientHttp2Fallback) { + BinaryMetadata(*this, true, false); +} - grpc_call_unref(c); - grpc_call_unref(s); +TEST_P(CoreEnd2endTest, BinaryMetadataServerHttp2FallbackClientTrueBinary) { + BinaryMetadata(*this, false, true); +} - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); +TEST_P(CoreEnd2endTest, BinaryMetadataServerTrueBinaryClientTrueBinary) { + BinaryMetadata(*this, true, true); } -void binary_metadata(const CoreTestConfiguration& config) { - test_request_response_with_metadata_and_payload(config); +TEST_P(CoreEnd2endTest, BinaryMetadataServerHttp2FallbackClientHttp2Fallback) { + BinaryMetadata(*this, false, false); } -void binary_metadata_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/call_creds.cc b/test/core/end2end/tests/call_creds.cc index eb5ab4ba3cc..731b18cadb7 100644 --- a/test/core/end2end/tests/call_creds.cc +++ b/test/core/end2end/tests/call_creds.cc @@ -16,56 +16,34 @@ // // -#include - -#include #include -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" + #include #include -#include -#include #include #include -#include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/security/credentials/credentials.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static const char iam_token[] = "token"; -static const char iam_selector[] = "selector"; -static const char overridden_iam_token[] = "overridden_token"; -static const char overridden_iam_selector[] = "overridden_selector"; -static const char fake_md_key[] = "fake_key"; -static const char fake_md_value[] = "fake_value"; -static const char overridden_fake_md_key[] = "overridden_fake_key"; -static const char overridden_fake_md_value[] = "overridden_fake_value"; +namespace grpc_core { +namespace { -typedef enum { NONE, OVERRIDE, DESTROY, FAIL } override_mode; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - bool use_secure_call_creds, int fail_server_auth_check) { - gpr_log(GPR_INFO, "Running test: %s%s/%s", test_name, - use_secure_call_creds ? "_with_secure_call_creds" - : "_with_insecure_call_creds", - config.name); - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - f->InitClient(grpc_core::ChannelArgs()); - grpc_core::ChannelArgs server_args; - if (fail_server_auth_check) { - server_args = server_args.Set(FAIL_AUTH_CHECK_SERVER_ARG_NAME, true); - } - f->InitServer(server_args); - return f; -} +const char iam_token[] = "token"; +const char iam_selector[] = "selector"; +const char overridden_iam_token[] = "overridden_token"; +const char overridden_iam_selector[] = "overridden_selector"; +const char fake_md_key[] = "fake_key"; +const char fake_md_value[] = "fake_value"; +const char overridden_fake_md_key[] = "overridden_fake_key"; +const char overridden_fake_md_value[] = "overridden_fake_value"; -static void print_auth_context(int is_client, const grpc_auth_context* ctx) { +void PrintAuthContext(bool is_client, const grpc_auth_context* ctx) { const grpc_auth_property* p; grpc_auth_property_iterator it; gpr_log(GPR_INFO, "%s peer:", is_client ? "client" : "server"); @@ -82,412 +60,270 @@ static void print_auth_context(int is_client, const grpc_auth_context* ctx) { } } -static void request_response_with_payload_and_call_creds( - const char* test_name, const CoreTestConfiguration& config, - override_mode mode, bool use_secure_call_creds) { - grpc_call* c = nullptr; - grpc_call* s = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_call_credentials* creds = nullptr; - grpc_auth_context* server_auth_context = nullptr; - grpc_auth_context* client_auth_context = nullptr; - - auto f = begin_test(config, test_name, use_secure_call_creds, 0); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); +void TestRequestResponseWithPayloadAndCallCreds(CoreEnd2endTest& test, + bool use_secure_call_creds) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + grpc_call_credentials* creds; if (use_secure_call_creds) { creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr); } else { creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); } - GPR_ASSERT(creds != nullptr); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - switch (mode) { - case NONE: - break; - case OVERRIDE: - grpc_call_credentials_release(creds); - if (use_secure_call_creds) { - creds = grpc_google_iam_credentials_create( - overridden_iam_token, overridden_iam_selector, nullptr); - } else { - creds = grpc_md_only_test_credentials_create(overridden_fake_md_key, - overridden_fake_md_value); - } - GPR_ASSERT(creds != nullptr); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - break; - case DESTROY: - GPR_ASSERT(grpc_call_set_credentials(c, nullptr) == GRPC_CALL_OK); - break; - case FAIL: - // Do nothing - break; + EXPECT_NE(creds, nullptr); + c.SetCredentials(creds); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + PrintAuthContext(false, s.GetAuthContext().get()); + PrintAuthContext(true, c.GetAuthContext().get()); + // Cannot set creds on the server call object. + EXPECT_NE(grpc_call_set_credentials(s.c_call(), nullptr), GRPC_CALL_OK); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage("hello you") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "hello world"); + EXPECT_EQ(server_message.payload(), "hello you"); + if (use_secure_call_creds) { + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), + iam_token); + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), + iam_selector); + } else { + EXPECT_EQ(s.GetInitialMetadata(fake_md_key), fake_md_value); } - grpc_call_credentials_release(creds); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +} - if (mode == FAIL) { - // Expect the call to fail since the channel credentials did not satisfy the - // minimum security level requirements. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); +void TestRequestResponseWithPayloadAndOverriddenCallCreds( + CoreEnd2endTest& test, bool use_secure_call_creds) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + grpc_call_credentials* creds; + if (use_secure_call_creds) { + creds = + grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr); } else { - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - server_auth_context = grpc_call_auth_context(s); - GPR_ASSERT(server_auth_context != nullptr); - print_auth_context(0, server_auth_context); - grpc_auth_context_release(server_auth_context); - - client_auth_context = grpc_call_auth_context(c); - GPR_ASSERT(client_auth_context != nullptr); - print_auth_context(1, client_auth_context); - grpc_auth_context_release(client_auth_context); - - // Cannot set creds on the server call object. - GPR_ASSERT(grpc_call_set_credentials(s, nullptr) != GRPC_CALL_OK); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - - switch (mode) { - case NONE: - if (use_secure_call_creds) { - GPR_ASSERT(contains_metadata( - &request_metadata_recv, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - iam_token)); - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - iam_selector)); - } else { - GPR_ASSERT(contains_metadata(&request_metadata_recv, fake_md_key, - fake_md_value)); - } - break; - case OVERRIDE: - if (use_secure_call_creds) { - GPR_ASSERT(contains_metadata( - &request_metadata_recv, GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - overridden_iam_token)); - GPR_ASSERT(contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - overridden_iam_selector)); - } else { - GPR_ASSERT(contains_metadata(&request_metadata_recv, - overridden_fake_md_key, - overridden_fake_md_value)); - } - break; - case DESTROY: - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - iam_token)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - iam_selector)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, - overridden_iam_token)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, - overridden_iam_selector)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, fake_md_key, - fake_md_value)); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, - overridden_fake_md_key, - overridden_fake_md_value)); - break; - case FAIL: - GPR_ASSERT(0); - } - grpc_call_unref(s); + creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); + } + EXPECT_NE(creds, nullptr); + c.SetCredentials(creds); + if (use_secure_call_creds) { + creds = grpc_google_iam_credentials_create( + overridden_iam_token, overridden_iam_selector, nullptr); + } else { + creds = grpc_md_only_test_credentials_create(overridden_fake_md_key, + overridden_fake_md_value); + } + c.SetCredentials(creds); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + PrintAuthContext(false, s.GetAuthContext().get()); + PrintAuthContext(true, c.GetAuthContext().get()); + // Cannot set creds on the server call object. + EXPECT_NE(grpc_call_set_credentials(s.c_call(), nullptr), GRPC_CALL_OK); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage("hello you") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "hello world"); + EXPECT_EQ(server_message.payload(), "hello you"); + if (use_secure_call_creds) { + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), + overridden_iam_token); + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), + overridden_iam_selector); + } else { + EXPECT_EQ(s.GetInitialMetadata(overridden_fake_md_key), + overridden_fake_md_value); } - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); } -static void test_request_response_with_payload_and_call_creds( - const CoreTestConfiguration& config, bool use_secure_call_creds) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_call_creds", config, NONE, - use_secure_call_creds); +void TestRequestResponseWithPayloadAndDeletedCallCreds( + CoreEnd2endTest& test, bool use_secure_call_creds) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + grpc_call_credentials* creds; + if (use_secure_call_creds) { + creds = + grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr); + } else { + creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); + } + EXPECT_NE(creds, nullptr); + c.SetCredentials(creds); + c.SetCredentials(nullptr); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + PrintAuthContext(false, s.GetAuthContext().get()); + PrintAuthContext(true, c.GetAuthContext().get()); + // Cannot set creds on the server call object. + EXPECT_NE(grpc_call_set_credentials(s.c_call(), nullptr), GRPC_CALL_OK); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage("hello you") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "hello world"); + EXPECT_EQ(server_message.payload(), "hello you"); + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), + absl::nullopt); + EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), + absl::nullopt); + EXPECT_EQ(s.GetInitialMetadata(fake_md_key), absl::nullopt); } -static void test_request_response_with_payload_and_overridden_call_creds( - const CoreTestConfiguration& config, bool use_secure_call_creds) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_overridden_call_creds", config, - OVERRIDE, use_secure_call_creds); +TEST_P(PerCallCredsOnInsecureTest, RequestWithServerRejectingClientCreds) { + InitClient(ChannelArgs()); + InitServer(ChannelArgs().Set(FAIL_AUTH_CHECK_SERVER_ARG_NAME, true)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create(); + auto* creds = + grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); + EXPECT_NE(creds, nullptr); + c.SetCredentials(creds); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAUTHENTICATED); } -static void test_request_response_with_payload_and_deleted_call_creds( - const CoreTestConfiguration& config, bool use_secure_call_creds) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_and_deleted_call_creds", config, - DESTROY, use_secure_call_creds); +TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndCallCreds) { + TestRequestResponseWithPayloadAndCallCreds(*this, true); } -static void test_request_response_with_payload_fail_to_send_call_creds( - const CoreTestConfiguration& config, bool use_secure_call_creds) { - request_response_with_payload_and_call_creds( - "test_request_response_with_payload_fail_to_send_call_creds", config, - FAIL, use_secure_call_creds); +TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndOverriddenCallCreds) { + TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, true); } -static void test_request_with_server_rejecting_client_creds( - const CoreTestConfiguration& config) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_call_credentials* creds; - - auto f = begin_test(config, "test_request_with_server_rejecting_client_creds", - false, 1); - grpc_core::CqVerifier cqv(f->cq()); - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); - GPR_ASSERT(creds != nullptr); - GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); - grpc_call_credentials_release(creds); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); +TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndDeletedCallCreds) { + TestRequestResponseWithPayloadAndDeletedCallCreds(*this, true); +} - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(error == GRPC_CALL_OK); +TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndInsecureCallCreds) { + TestRequestResponseWithPayloadAndCallCreds(*this, false); +} - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); +TEST_P(PerCallCredsTest, + RequestResponseWithPayloadAndOverriddenInsecureCallCreds) { + TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, false); +} - GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); +TEST_P(PerCallCredsTest, + RequestResponseWithPayloadAndDeletedInsecureCallCreds) { + TestRequestResponseWithPayloadAndDeletedCallCreds(*this, false); +} - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); +TEST_P(PerCallCredsOnInsecureTest, + RequestResponseWithPayloadAndInsecureCallCreds) { + TestRequestResponseWithPayloadAndCallCreds(*this, false); +} - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); +TEST_P(PerCallCredsOnInsecureTest, + RequestResponseWithPayloadAndOverriddenInsecureCallCreds) { + TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, false); +} - grpc_call_unref(c); +TEST_P(PerCallCredsOnInsecureTest, + RequestResponseWithPayloadAndDeletedInsecureCallCreds) { + TestRequestResponseWithPayloadAndDeletedCallCreds(*this, false); } -void call_creds(const CoreTestConfiguration& config) { - // Test fixtures that support call credentials with a minimum security level - // of GRPC_PRIVACY_AND_INTEGRITY - if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) { - test_request_response_with_payload_and_call_creds(config, true); - test_request_response_with_payload_and_overridden_call_creds(config, true); - test_request_response_with_payload_and_deleted_call_creds(config, true); - } - // Test that fixtures that support call credentials with a minimum security - // level of GRPC_SECURITY_NONE cannot send call credentials that require - // higher security level - if (config.feature_mask & - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE) { - test_request_response_with_payload_fail_to_send_call_creds(config, true); - } - // Fixtures that support sending call credentials should be able to send call - // credentials of security level GRPC_SECURITY_NONE. - if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS || - config.feature_mask & - FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE) { - test_request_response_with_payload_and_call_creds(config, false); - test_request_response_with_payload_and_overridden_call_creds(config, false); - test_request_response_with_payload_and_deleted_call_creds(config, false); - test_request_with_server_rejecting_client_creds(config); - } +TEST_P(PerCallCredsOnInsecureTest, FailToSendCallCreds) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + grpc_call_credentials* creds; + creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr); + EXPECT_NE(creds, nullptr); + c.SetCredentials(creds); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + // Expect the call to fail since the channel credentials did not satisfy the + // minimum security level requirements. + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAUTHENTICATED); } -void call_creds_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/call_host_override.cc b/test/core/end2end/tests/call_host_override.cc index c947d021d72..7887c6d5cdc 100644 --- a/test/core/end2end/tests/call_host_override.cc +++ b/test/core/end2end/tests/call_host_override.cc @@ -16,162 +16,54 @@ // // -#include - -#include -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient( - grpc_core::ChannelArgs::FromC(client_args) - .Set(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, "foo.test.google.fr:1234")); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - return f; -} - -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/foo"), - get_host_override_slice("foo.test.google.fr:1234", config), deadline, - nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(error == GRPC_CALL_OK); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(error == GRPC_CALL_OK); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(error == GRPC_CALL_OK); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - validate_host_override_string("foo.test.google.fr:1234", call_details.host, - config); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} -void call_host_override(const CoreTestConfiguration& config) { - test_invoke_simple_request(config); +namespace grpc_core { +namespace { + +TEST_P(CoreClientChannelTest, CallHostOverride) { + InitClient(ChannelArgs().Set(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, + "foo.test.google.fr:1234")); + InitServer(ChannelArgs()); + auto c = NewClientCall("/foo") + .Timeout(Duration::Seconds(5)) + .Host("foo.test.google.fr:1234") + .Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_EQ(s.host(), "foo.test.google.fr:1234"); + EXPECT_FALSE(client_close.was_cancelled()); } -void call_host_override_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_after_accept.cc b/test/core/end2end/tests/cancel_after_accept.cc index 49fb414d098..33d9da9dfbe 100644 --- a/test/core/end2end/tests/cancel_after_accept.cc +++ b/test/core/end2end/tests/cancel_after_accept.cc @@ -16,216 +16,80 @@ // // -#include - -#include #include -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - cancellation_mode mode, bool use_service_config, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "%s", std::string(80, '*').c_str()); - gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, - mode.name, use_service_config ? "service_config" : "client_api"); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { // Cancel after accept, no payload -static void test_cancel_after_accept(const CoreTestConfiguration& config, - cancellation_mode mode, - bool use_service_config) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - grpc_call* s; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - grpc_channel_args* args = nullptr; - if (use_service_config) { - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" },\n" - " { \"service\": \"unused\" }\n" - " ],\n" - " \"timeout\": \"5s\"\n" - " } ]\n" - "}"); - args = grpc_channel_args_copy_and_add(args, &arg, 1); - } - - auto f = begin_test(config, "cancel_after_accept", mode, use_service_config, - args, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = use_service_config - ? gpr_inf_future(GPR_CLOCK_MONOTONIC) - : grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(2)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); +void CancelAfterAccept(CoreEnd2endTest& test, + std::unique_ptr cancellation_mode, + Duration timeout) { + auto c = test.NewClientCall("/service/method").Timeout(timeout).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); + auto s = test.RequestCall(2); + test.Expect(2, true); + test.Step(); + CoreEnd2endTest::IncomingMessage client_message; + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(3) + .RecvMessage(client_message) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .RecvCloseOnServer(client_close); + cancellation_mode->Apply(c); + test.Expect(1, true); + test.Expect(3, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(cancellation_mode->ExpectedStatus(), + GRPC_STATUS_INTERNAL)); + EXPECT_TRUE(client_close.was_cancelled()); +} - if (args != nullptr) { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } +TEST_P(CoreEnd2endTest, CancelAfterAccept) { + CancelAfterAccept(*this, std::make_unique(), + Duration::Seconds(5)); } -void cancel_after_accept(const CoreTestConfiguration& config) { - unsigned i; +TEST_P(CoreDeadlineTest, DeadlineAfterAccept) { + CancelAfterAccept(*this, std::make_unique(), + Duration::Seconds(5)); +} - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - continue; - } - test_cancel_after_accept(config, cancellation_modes[i], - false /* use_service_config */); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - test_cancel_after_accept(config, cancellation_modes[i], - true /* use_service_config */); - } - } +TEST_P(CoreClientChannelTest, DeadlineAfterAcceptWithServiceConfig) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" },\n" + " { \"service\": \"unused\" }\n" + " ],\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}")); + CancelAfterAccept(*this, std::make_unique(), + Duration::Infinity()); } -void cancel_after_accept_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_after_client_done.cc b/test/core/end2end/tests/cancel_after_client_done.cc index a1c2fb7dfa9..244a4e80f95 100644 --- a/test/core/end2end/tests/cancel_after_client_done.cc +++ b/test/core/end2end/tests/cancel_after_client_done.cc @@ -16,183 +16,62 @@ // // -#include - -#include #include -#include -#include -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - cancellation_mode mode, grpc_channel_args* client_args, - grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, - mode.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { // Cancel after accept with a writes closed, no payload -static void test_cancel_after_accept_and_writes_closed( - const CoreTestConfiguration& config, cancellation_mode mode) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - grpc_call* s; - auto f = begin_test(config, "test_cancel_after_accept_and_writes_closed", - mode, nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(2)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); +void CancelAfterClientDone( + CoreEnd2endTest& test, + std::unique_ptr cancellation_mode) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .SendCloseFromClient(); + auto s = test.RequestCall(2); + test.Expect(2, true); + test.Step(); + CoreEnd2endTest::IncomingMessage client_message; + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(3) + .RecvMessage(client_message) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .RecvCloseOnServer(client_close); + cancellation_mode->Apply(c); + test.Expect(1, true); + test.Expect(3, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(cancellation_mode->ExpectedStatus(), + GRPC_STATUS_INTERNAL)); + EXPECT_TRUE(client_close.was_cancelled()); } -void cancel_after_client_done(const CoreTestConfiguration& config) { - unsigned i; +TEST_P(CoreEnd2endTest, CancelAfterClientDone) { + CancelAfterClientDone(*this, std::make_unique()); +} - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - continue; - } - test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]); - } +TEST_P(CoreDeadlineTest, DeadlineAfterClientDone) { + CancelAfterClientDone(*this, std::make_unique()); } -void cancel_after_client_done_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_after_invoke.cc b/test/core/end2end/tests/cancel_after_invoke.cc index 7def3727448..d72ff77b1bc 100644 --- a/test/core/end2end/tests/cancel_after_invoke.cc +++ b/test/core/end2end/tests/cancel_after_invoke.cc @@ -16,143 +16,128 @@ // // -#include -#include -#include - -#include #include -#include -#include -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - cancellation_mode mode, size_t test_ops, grpc_channel_args* client_args, - grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s/%s [%" PRIdPTR " ops]", test_name, - config.name, mode.name, test_ops); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; + +namespace grpc_core { + +void CancelAfterInvoke6(CoreEnd2endTest& test, + std::unique_ptr mode) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .SendCloseFromClient() + .RecvMessage(server_message); + mode->Apply(c); + test.Expect(1, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(mode->ExpectedStatus(), GRPC_STATUS_INTERNAL)); +} + +void CancelAfterInvoke5(CoreEnd2endTest& test, + std::unique_ptr mode) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .SendCloseFromClient(); + mode->Apply(c); + test.Expect(1, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(mode->ExpectedStatus(), GRPC_STATUS_INTERNAL)); +} + +void CancelAfterInvoke4(CoreEnd2endTest& test, + std::unique_ptr mode) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)); + mode->Apply(c); + test.Expect(1, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(mode->ExpectedStatus(), GRPC_STATUS_INTERNAL)); +} + +void CancelAfterInvoke3(CoreEnd2endTest& test, + std::unique_ptr mode) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}); + mode->Apply(c); + test.Expect(1, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(mode->ExpectedStatus(), GRPC_STATUS_INTERNAL)); +} + +TEST_P(CoreEnd2endTest, CancelAfterInvoke6) { + CancelAfterInvoke6(*this, std::make_unique()); +} + +TEST_P(CoreEnd2endTest, CancelAfterInvoke5) { + CancelAfterInvoke5(*this, std::make_unique()); +} + +TEST_P(CoreEnd2endTest, CancelAfterInvoke4) { + CancelAfterInvoke4(*this, std::make_unique()); +} + +TEST_P(CoreEnd2endTest, CancelAfterInvoke3) { + CancelAfterInvoke3(*this, std::make_unique()); +} + +TEST_P(CoreDeadlineTest, DeadlineAfterInvoke6) { + CancelAfterInvoke6(*this, std::make_unique()); +} + +TEST_P(CoreDeadlineTest, DeadlineAfterInvoke5) { + CancelAfterInvoke5(*this, std::make_unique()); } -// Cancel after invoke, no payload -static void test_cancel_after_invoke(const CoreTestConfiguration& config, - cancellation_mode mode, size_t test_ops) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - auto f = begin_test(config, "test_cancel_after_invoke", mode, test_ops, - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, test_ops, grpc_core::CqVerifier::tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); +TEST_P(CoreDeadlineTest, DeadlineAfterInvoke4) { + CancelAfterInvoke4(*this, std::make_unique()); } -void cancel_after_invoke(const CoreTestConfiguration& config) { - unsigned i, j; - - for (j = 3; j < 6; j++) { - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && - cancellation_modes[i].expect_status == - GRPC_STATUS_DEADLINE_EXCEEDED) { - continue; - } - test_cancel_after_invoke(config, cancellation_modes[i], j); - } - } +TEST_P(CoreDeadlineTest, DeadlineAfterInvoke3) { + CancelAfterInvoke3(*this, std::make_unique()); } -void cancel_after_invoke_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_after_round_trip.cc b/test/core/end2end/tests/cancel_after_round_trip.cc index 0bd4e94eb0d..a353d2fa479 100644 --- a/test/core/end2end/tests/cancel_after_round_trip.cc +++ b/test/core/end2end/tests/cancel_after_round_trip.cc @@ -16,247 +16,83 @@ // // -#include - -#include #include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - cancellation_mode mode, bool use_service_config, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, - mode.name, use_service_config ? "service_config" : "client_api"); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +namespace grpc_core { +namespace { + +void CancelAfterRoundTrip(CoreEnd2endTest& test, + std::unique_ptr mode, + Duration timeout) { + auto c = test.NewClientCall("/service/method").Timeout(timeout).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(100)) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102) + .RecvMessage(client_message) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(100)); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + CoreEnd2endTest::IncomingMessage server_message_2; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(2).RecvMessage(server_message_2).RecvStatusOnClient(server_status); + mode->Apply(c); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103).RecvCloseOnServer(client_close).SendMessage(RandomSlice(100)); + test.Expect(2, true); + test.Expect(103, true); + test.Step(); + EXPECT_THAT(server_status.status(), + ::testing::AnyOf(mode->ExpectedStatus(), GRPC_STATUS_INTERNAL)); + EXPECT_TRUE(client_close.was_cancelled()); } -// Cancel after accept, no payload -static void test_cancel_after_round_trip(const CoreTestConfiguration& config, - cancellation_mode mode, - bool use_service_config) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - grpc_call* s; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload1 = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* response_payload2 = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - int was_cancelled = 2; - - grpc_channel_args* args = nullptr; - if (use_service_config) { - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"timeout\": \"5s\"\n" - " } ]\n" - "}"); - args = grpc_channel_args_copy_and_add(args, &arg, 1); - } - - auto f = begin_test(config, "cancel_after_round_trip", mode, - use_service_config, args, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = use_service_config - ? gpr_inf_future(GPR_CLOCK_MONOTONIC) - : grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload1; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - request_payload_recv = nullptr; - response_payload_recv = nullptr; - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload2; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Verify(); - - GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); - GPR_ASSERT(was_cancelled == 1); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload1); - grpc_byte_buffer_destroy(response_payload2); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); - - grpc_call_unref(c); - grpc_call_unref(s); - - if (args != nullptr) { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(args); - } +TEST_P(CoreEnd2endTest, CancelAfterRoundTrip) { + CancelAfterRoundTrip(*this, std::make_unique(), + Duration::Seconds(5)); } -void cancel_after_round_trip(const CoreTestConfiguration& config) { - unsigned i; +TEST_P(CoreDeadlineTest, DeadlineAfterRoundTrip) { + CancelAfterRoundTrip(*this, std::make_unique(), + Duration::Seconds(5)); +} - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - continue; - } - test_cancel_after_round_trip(config, cancellation_modes[i], - false /* use_service_config */); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && - cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { - test_cancel_after_round_trip(config, cancellation_modes[i], - true /* use_service_config */); - } - } +TEST_P(CoreClientChannelTest, DeadlineAfterAcceptWithServiceConfig) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}")); + CancelAfterRoundTrip(*this, std::make_unique(), + Duration::Infinity()); } -void cancel_after_round_trip_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_before_invoke.cc b/test/core/end2end/tests/cancel_before_invoke.cc index 2ce710f26c7..4dd5e0feeeb 100644 --- a/test/core/end2end/tests/cancel_before_invoke.cc +++ b/test/core/end2end/tests/cancel_before_invoke.cc @@ -16,136 +16,93 @@ // // -#include -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, size_t num_ops, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, - config.name, num_ops); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +namespace grpc_core { + +TEST_P(CoreEnd2endTest, CancelBeforeInvoke6) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); } -// Cancel before invoke -static void test_cancel_before_invoke(const CoreTestConfiguration& config, - size_t test_ops) { - grpc_op ops[6]; - grpc_op* op; - grpc_call* c; - auto f = - begin_test(config, "cancel_before_invoke", test_ops, nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, nullptr)); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, test_ops, grpc_core::CqVerifier::tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Filter based stack tracks this as a failed op, promise based stack tracks - // it as a successful one with a failed request. The latter probably makes - // more sense, but since we can't tell from outside which case we have we - // accept either. - cqv.Expect(grpc_core::CqVerifier::tag(1), grpc_core::CqVerifier::AnyStatus()); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_CANCELLED); +TEST_P(CoreEnd2endTest, CancelBeforeInvoke5) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); +} - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); +TEST_P(CoreEnd2endTest, CancelBeforeInvoke4) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)) + .SendCloseFromClient(); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); +} - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(details); +TEST_P(CoreEnd2endTest, CancelBeforeInvoke3) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .SendInitialMetadata({}) + .SendMessage(RandomSlice(1024)); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); +} - grpc_call_unref(c); +TEST_P(CoreEnd2endTest, CancelBeforeInvoke2) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1).RecvStatusOnClient(server_status).SendInitialMetadata({}); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); } -void cancel_before_invoke(const CoreTestConfiguration& config) { - size_t i; - for (i = 1; i <= 6; i++) { - test_cancel_before_invoke(config, i); - } +TEST_P(CoreEnd2endTest, CancelBeforeInvoke1) { + auto c = NewClientCall("/service/method").Create(); + c.Cancel(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1).RecvStatusOnClient(server_status); + Expect(1, AnyStatus()); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); } -void cancel_before_invoke_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.cc b/test/core/end2end/tests/cancel_in_a_vacuum.cc index 04ed84a320b..135475068e7 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.cc +++ b/test/core/end2end/tests/cancel_in_a_vacuum.cc @@ -16,58 +16,18 @@ // // -#include -#include +#include "gtest/gtest.h" -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - cancellation_mode mode, grpc_channel_args* client_args, - grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s/%s", test_name, config.name, - mode.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -// Cancel and do nothing -static void test_cancel_in_a_vacuum(const CoreTestConfiguration& config, - cancellation_mode mode) { - grpc_call* c; - auto f = - begin_test(config, "test_cancel_in_a_vacuum", mode, nullptr, nullptr); +namespace grpc_core { - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - grpc_call_unref(c); +TEST_P(CoreEnd2endTest, CancelInAVacuum) { + NewClientCall("/service/method").Create().Cancel(); } -void cancel_in_a_vacuum(const CoreTestConfiguration& config) { - unsigned i; - - for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { - test_cancel_in_a_vacuum(config, cancellation_modes[i]); - } +TEST_P(CoreDeadlineTest, DeadlineInAVacuum) { + NewClientCall("/service/method").Create(); } -void cancel_in_a_vacuum_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/cancel_test_helpers.h b/test/core/end2end/tests/cancel_test_helpers.h index 82324a26d14..0411fb1905f 100644 --- a/test/core/end2end/tests/cancel_test_helpers.h +++ b/test/core/end2end/tests/cancel_test_helpers.h @@ -19,25 +19,31 @@ #ifndef GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H #define GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H -#include #include -typedef struct { - const char* name; - grpc_call_error (*initiate_cancel)(grpc_call* call, void* reserved); - grpc_status_code expect_status; - const char* expect_details; -} cancellation_mode; +#include "test/core/end2end/end2end_tests.h" -static grpc_call_error wait_for_deadline(grpc_call* /*call*/, void* reserved) { - (void)reserved; - return GRPC_CALL_OK; -} +namespace grpc_core { +class CancellationMode { + public: + virtual void Apply(CoreEnd2endTest::Call& call) = 0; + virtual grpc_status_code ExpectedStatus() = 0; + virtual ~CancellationMode() = default; +}; + +class CancelCancellationMode : public CancellationMode { + public: + void Apply(CoreEnd2endTest::Call& call) override { call.Cancel(); } + grpc_status_code ExpectedStatus() override { return GRPC_STATUS_CANCELLED; } +}; -static const cancellation_mode cancellation_modes[] = { - {"cancel", grpc_call_cancel, GRPC_STATUS_CANCELLED, "CANCELLED"}, - {"deadline", wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED, - "Deadline Exceeded"}, +class DeadlineCancellationMode : public CancellationMode { + public: + void Apply(CoreEnd2endTest::Call&) override {} + grpc_status_code ExpectedStatus() override { + return GRPC_STATUS_DEADLINE_EXCEEDED; + } }; +} // namespace grpc_core #endif // GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H diff --git a/test/core/end2end/tests/cancel_with_status.cc b/test/core/end2end/tests/cancel_with_status.cc index 7ea7d156bc2..fa97a1bb20a 100644 --- a/test/core/end2end/tests/cancel_with_status.cc +++ b/test/core/end2end/tests/cancel_with_status.cc @@ -16,122 +16,89 @@ // // -#include -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include #include -#include #include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, size_t num_ops, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, - config.name, num_ops); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f, size_t num_ops) { - grpc_call* c; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - GPR_ASSERT(num_ops <= (size_t)(op - ops)); - error = grpc_call_start_batch(c, ops, num_ops, grpc_core::CqVerifier::tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +namespace grpc_core { +namespace { +TEST_P(CoreEnd2endTest, CancelWithStatus1) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1).RecvStatusOnClient(server_status); char* dynamic_string = gpr_strdup("xyz"); - grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, dynamic_string, - nullptr); + c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string); // The API of \a description allows for it to be a dynamic/non-const // string, test this guarantee. gpr_free(dynamic_string); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); +} - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); +TEST_P(CoreEnd2endTest, CancelWithStatus2) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata); + char* dynamic_string = gpr_strdup("xyz"); + c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string); + // The API of \a description allows for it to be a dynamic/non-const + // string, test this guarantee. + gpr_free(dynamic_string); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -static void test_invoke_simple_request(const CoreTestConfiguration& config, - size_t num_ops) { - auto f = begin_test(config, "test_invoke_simple_request", num_ops, nullptr, - nullptr); - simple_request_body(config, f.get(), num_ops); +TEST_P(CoreEnd2endTest, CancelWithStatus3) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}); + char* dynamic_string = gpr_strdup("xyz"); + c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string); + // The API of \a description allows for it to be a dynamic/non-const + // string, test this guarantee. + gpr_free(dynamic_string); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -void cancel_with_status(const CoreTestConfiguration& config) { - size_t i; - for (i = 1; i <= 4; i++) { - test_invoke_simple_request(config, i); - } +TEST_P(CoreEnd2endTest, CancelWithStatus4) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}) + .SendCloseFromClient(); + char* dynamic_string = gpr_strdup("xyz"); + c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string); + // The API of \a description allows for it to be a dynamic/non-const + // string, test this guarantee. + gpr_free(dynamic_string); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -void cancel_with_status_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 8227832dc27..d5e7f6d2938 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -18,252 +18,145 @@ #include "src/core/lib/channel/channelz.h" -#include - -#include -#include #include +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/server.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +using testing::HasSubstr; +using testing::Not; + +namespace grpc_core { +namespace { + +void RunOneRequest(CoreEnd2endTest& test, bool request_is_success) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer( + request_is_success ? GRPC_STATUS_OK : GRPC_STATUS_UNIMPLEMENTED, + "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); } -static void run_one_request(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f, bool request_is_success) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->data.recv_status_on_client.error_string = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(CoreEnd2endTest, Channelz) { + auto args = ChannelArgs() + .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 0) + .Set(GRPC_ARG_ENABLE_CHANNELZ, true); + InitServer(args); + InitClient(args); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); + channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(client()); + ASSERT_NE(channelz_channel, nullptr); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = - request_is_success ? GRPC_STATUS_OK : GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -static void test_channelz(const CoreTestConfiguration& config) { - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), - 0), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), true)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - - auto f = begin_test(config, "test_channelz", &args, &args); - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(f->client()); - GPR_ASSERT(channelz_channel != nullptr); - - grpc_core::channelz::ServerNode* channelz_server = - grpc_core::Server::FromC(f->server())->channelz_node(); - GPR_ASSERT(channelz_server != nullptr); + channelz::ServerNode* channelz_server = + Server::FromC(server())->channelz_node(); + ASSERT_NE(channelz_server, nullptr); std::string json = channelz_channel->RenderJsonString(); // nothing is present yet - GPR_ASSERT(json.find("\"callsStarted\"") == json.npos); - GPR_ASSERT(json.find("\"callsFailed\"") == json.npos); - GPR_ASSERT(json.find("\"callsSucceeded\"") == json.npos); + EXPECT_THAT(json, Not(HasSubstr("\"callsStarted\""))); + EXPECT_THAT(json, Not(HasSubstr("\"callsFailed\""))); + EXPECT_THAT(json, Not(HasSubstr("\"callsSucceeded\""))); // one successful request - run_one_request(config, f.get(), true); + RunOneRequest(*this, true); json = channelz_channel->RenderJsonString(); - GPR_ASSERT(json.find("\"callsStarted\":\"1\"") != json.npos); - GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); + EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"1\"")); + EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\"")); // one failed request - run_one_request(config, f.get(), false); + RunOneRequest(*this, false); json = channelz_channel->RenderJsonString(); - GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos); - GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos); - GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); + EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"2\"")); + EXPECT_THAT(json, HasSubstr("\"callsFailed\":\"1\"")); + EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\"")); // channel tracing is not enabled, so these should not be preset. - GPR_ASSERT(json.find("\"trace\"") == json.npos); - GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos); - GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos); + EXPECT_THAT(json, Not(HasSubstr("\"trace\""))); + EXPECT_THAT(json, Not(HasSubstr("\"description\":\"Channel created\""))); + EXPECT_THAT(json, Not(HasSubstr("\"severity\":\"CT_INFO\""))); json = channelz_server->RenderJsonString(); - GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos); - GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos); - GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); + EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"2\"")); + EXPECT_THAT(json, HasSubstr("\"callsFailed\":\"1\"")); + EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\"")); // channel tracing is not enabled, so these should not be preset. - GPR_ASSERT(json.find("\"trace\"") == json.npos); - GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos); - GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos); + EXPECT_THAT(json, Not(HasSubstr("\"trace\""))); + EXPECT_THAT(json, Not(HasSubstr("\"description\":\"Channel created\""))); + EXPECT_THAT(json, Not(HasSubstr("\"severity\":\"CT_INFO\""))); json = channelz_server->RenderServerSockets(0, 100); - GPR_ASSERT(json.find("\"end\":true") != json.npos); + EXPECT_THAT(json, HasSubstr("\"end\":true")); } -static void test_channelz_with_channel_trace( - const CoreTestConfiguration& config) { - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), - 1024 * 1024), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), true)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; +TEST_P(CoreEnd2endTest, ChannelzWithChannelTrace) { + auto args = + ChannelArgs() + .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024 * 1024) + .Set(GRPC_ARG_ENABLE_CHANNELZ, true); + InitServer(args); + InitClient(args); - auto f = begin_test(config, "test_channelz_with_channel_trace", &args, &args); - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(f->client()); - GPR_ASSERT(channelz_channel != nullptr); + channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(client()); + ASSERT_NE(channelz_channel, nullptr); - grpc_core::channelz::ServerNode* channelz_server = - grpc_core::Server::FromC(f->server())->channelz_node(); - GPR_ASSERT(channelz_server != nullptr); + channelz::ServerNode* channelz_server = + Server::FromC(server())->channelz_node(); + ASSERT_NE(channelz_server, nullptr); - run_one_request(config, f.get(), true); + RunOneRequest(*this, true); std::string json = channelz_channel->RenderJsonString(); - GPR_ASSERT(json.find("\"trace\"") != json.npos); - GPR_ASSERT(json.find("\"description\":\"Channel created\"") != json.npos); - GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos); + EXPECT_THAT(json, HasSubstr("\"trace\"")); + EXPECT_THAT(json, HasSubstr("\"description\":\"Channel created\"")); + EXPECT_THAT(json, HasSubstr("\"severity\":\"CT_INFO\"")); json = channelz_server->RenderJsonString(); - GPR_ASSERT(json.find("\"trace\"") != json.npos); - GPR_ASSERT(json.find("\"description\":\"Server created\"") != json.npos); - GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos); -} - -static void test_channelz_disabled(const CoreTestConfiguration& config) { - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), - 0), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), false)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - - auto f = begin_test(config, "test_channelz_disabled", &args, &args); - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(f->client()); - GPR_ASSERT(channelz_channel == nullptr); - // one successful request - run_one_request(config, f.get(), true); - GPR_ASSERT(channelz_channel == nullptr); + EXPECT_THAT(json, HasSubstr("\"trace\"")); + EXPECT_THAT(json, HasSubstr("\"description\":\"Server created\"")); + EXPECT_THAT(json, HasSubstr("\"severity\":\"CT_INFO\"")); } -void channelz(const CoreTestConfiguration& config) { - test_channelz(config); - test_channelz_with_channel_trace(config); - test_channelz_disabled(config); +TEST_P(CoreEnd2endTest, ChannelzDisabled) { + auto args = ChannelArgs() + .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 0) + .Set(GRPC_ARG_ENABLE_CHANNELZ, false); + InitServer(args); + InitClient(args); + channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(client()); + EXPECT_EQ(channelz_channel, nullptr); + RunOneRequest(*this, true); } -void channelz_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/client_streaming.cc b/test/core/end2end/tests/client_streaming.cc index 705a494cd44..e2220d54eb1 100644 --- a/test/core/end2end/tests/client_streaming.cc +++ b/test/core/end2end/tests/client_streaming.cc @@ -16,214 +16,70 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Client streaming test where the client sends a bunch of messages and the // server reads them. After reading some messages, the server sends the status. // Client writes fail after that due to the end of stream and the client // subsequently requests and receives the status. -static void test_client_streaming(const CoreTestConfiguration& config, - int messages) { - auto f = begin_test(config, "test_client_streaming", nullptr, nullptr); - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* request_payload = nullptr; - int i; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(100), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(101), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - +void ClientStreaming(CoreEnd2endTest& test, int messages) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1).SendInitialMetadata({}).RecvInitialMetadata( + server_initial_metadata); + auto s = test.RequestCall(100); + test.Expect(100, true); + test.Step(); + s.NewBatch(101).SendInitialMetadata({}); + test.Expect(101, true); + test.Expect(1, true); + test.Step(); // Client writes bunch of messages and server reads them - for (i = 0; i < messages; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - grpc_byte_buffer_destroy(request_payload); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Verify(); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - grpc_byte_buffer_destroy(request_payload_recv); + for (int i = 0; i < messages; i++) { + c.NewBatch(2).SendMessage("hello world"); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + test.Expect(2, true); + test.Expect(102, true); + test.Step(); + EXPECT_EQ(client_message.payload(), "hello world"); } // Server sends status denoting end of stream - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); + s.NewBatch(103).SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + test.Expect(103, true); + test.Step(); // Do an empty verify to make sure that the client receives the status - cqv.VerifyEmpty(); + test.Step(); // Client tries sending another message which should fail - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - grpc_byte_buffer_destroy(request_payload); - cqv.Expect(grpc_core::CqVerifier::tag(103), false); - cqv.Verify(); + c.NewBatch(3).SendMessage("hello world"); + test.Expect(3, false); + test.Step(); // Client sends close and requests status - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(request_payload_slice); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_slice_unref(details); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(4).SendCloseFromClient().RecvStatusOnClient(server_status); + test.Expect(4, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -void client_streaming(const CoreTestConfiguration& config) { - for (int i = 0; i < 10; i++) { - test_client_streaming(config, i); - } -} +TEST_P(CoreEnd2endTest, ClientStreaming0) { ClientStreaming(*this, 0); } +TEST_P(CoreEnd2endTest, ClientStreaming1) { ClientStreaming(*this, 1); } +TEST_P(CoreEnd2endTest, ClientStreaming3) { ClientStreaming(*this, 3); } +TEST_P(CoreEnd2endTest, ClientStreaming10) { ClientStreaming(*this, 10); } +TEST_P(CoreEnd2endTest, ClientStreaming30) { ClientStreaming(*this, 30); } -void client_streaming_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/compressed_payload.cc b/test/core/end2end/tests/compressed_payload.cc index 7a72fe0a349..1d9a94c80e5 100644 --- a/test/core/end2end/tests/compressed_payload.cc +++ b/test/core/end2end/tests/compressed_payload.cc @@ -17,627 +17,414 @@ // #include -#include -#include #include -#include #include +#include -#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" +#include "gtest/gtest.h" -#include #include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/bitset.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/call_test_only.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - const grpc_channel_args* client_args, const grpc_channel_args* server_args, - bool decompress_in_core) { - gpr_log(GPR_INFO, "Running test: %s%s/%s", test_name, - decompress_in_core ? "" : "_with_decompression_disabled", - config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -static void request_for_disabled_algorithm( - const CoreTestConfiguration& config, const char* test_name, - uint32_t send_flags_bitmask, - grpc_compression_algorithm algorithm_to_disable, - grpc_compression_algorithm requested_client_compression_algorithm, - grpc_status_code expected_error, grpc_metadata* client_metadata, - bool decompress_in_core) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice; - grpc_byte_buffer* request_payload; - grpc_core::ChannelArgs client_args; - grpc_core::ChannelArgs server_args; - - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char str[1024]; - - memset(str, 'x', 1023); - str[1023] = '\0'; - request_payload_slice = grpc_slice_from_copied_string(str); - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - - client_args = - grpc_core::ChannelArgs().Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - requested_client_compression_algorithm); - server_args = - grpc_core::ChannelArgs() - .Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE) - .Set(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, - grpc_core::BitSet() - .SetAll(true) - .Set(algorithm_to_disable, false) - .ToInt()); - if (!decompress_in_core) { - client_args = - client_args.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); - server_args = - server_args.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); +namespace grpc_core { +namespace { + +class TestConfigurator { + public: + explicit TestConfigurator(CoreEnd2endTest& test) : test_(test) {} + + TestConfigurator& DisableAlgorithmAtServer( + grpc_compression_algorithm algorithm) { + server_args_ = + server_args_.Set(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, + BitSet() + .SetAll(true) + .Set(algorithm, false) + .ToInt()); + return *this; } - auto f = begin_test(config, test_name, client_args.ToC().get(), - server_args.ToC().get(), decompress_in_core); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_metadata != nullptr) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_metadata; - } else { - op->data.send_initial_metadata.count = 0; + TestConfigurator& ClientDefaultAlgorithm( + grpc_compression_algorithm algorithm) { + client_args_ = + client_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm); + return *this; + } + + TestConfigurator& ServerDefaultAlgorithm( + grpc_compression_algorithm algorithm) { + server_args_ = + server_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm); + return *this; } - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = send_flags_bitmask; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), false); - - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Verify(); - - // call was cancelled (closed) ... - GPR_ASSERT(was_cancelled != 0); - // with a certain error - GPR_ASSERT(status == expected_error); - - const char* algo_name = nullptr; - GPR_ASSERT(grpc_compression_algorithm_name(algorithm_to_disable, &algo_name)); - std::string expected_details = - absl::StrFormat("Compression algorithm '%s' is disabled.", algo_name); - // and we expect a specific reason for it - GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details.c_str())); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_slice_unref(request_payload_slice); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} -static void request_with_payload_template_inner( - const CoreTestConfiguration& config, const char* test_name, - uint32_t client_send_flags_bitmask, - grpc_compression_algorithm default_client_channel_compression_algorithm, - grpc_compression_algorithm default_server_channel_compression_algorithm, - grpc_compression_algorithm expected_algorithm_from_client, - grpc_compression_algorithm expected_algorithm_from_server, - grpc_metadata* client_init_metadata, bool set_server_level, - grpc_compression_level server_compression_level, - bool send_message_before_initial_metadata, bool decompress_in_core) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice; - grpc_byte_buffer* request_payload = nullptr; - grpc_core::ChannelArgs client_args; - grpc_core::ChannelArgs server_args; - - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload; - grpc_byte_buffer* response_payload_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char request_str[1024]; - char response_str[1024]; - - memset(request_str, 'x', 1023); - request_str[1023] = '\0'; - - memset(response_str, 'y', 1023); - response_str[1023] = '\0'; - - request_payload_slice = grpc_slice_from_copied_string(request_str); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string(response_str); - - client_args = grpc_core::ChannelArgs().Set( - GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - default_client_channel_compression_algorithm); - server_args = grpc_core::ChannelArgs().Set( - GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, - default_server_channel_compression_algorithm); - if (!decompress_in_core) { - client_args = - client_args.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); - server_args = - server_args.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); + TestConfigurator& DecompressInApp() { + client_args_ = + client_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); + server_args_ = + server_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false); + return *this; } - auto f = begin_test(config, test_name, client_args.ToC().get(), - server_args.ToC().get(), decompress_in_core); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - if (send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); + + TestConfigurator& ExpectedAlgorithmFromClient( + grpc_compression_algorithm algorithm) { + expected_algorithm_from_client_ = algorithm; + return *this; } - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - if (client_init_metadata != nullptr) { - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = client_init_metadata; - } else { - op->data.send_initial_metadata.count = 0; + + TestConfigurator& ExpectedAlgorithmFromServer( + grpc_compression_algorithm algorithm) { + expected_algorithm_from_server_ = algorithm; + return *this; } - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(100), true); - cqv.Verify(); - - GPR_ASSERT(grpc_core::BitCount( - grpc_call_test_only_get_encodings_accepted_by_peer(s)) == - GRPC_COMPRESS_ALGORITHMS_COUNT); - GPR_ASSERT( - grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_NONE) != 0); - GPR_ASSERT( - grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_DEFLATE) != 0); - GPR_ASSERT( - grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s), - GRPC_COMPRESS_GZIP) != 0); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - if (set_server_level) { - op->data.send_initial_metadata.maybe_compression_level.is_set = true; - op->data.send_initial_metadata.maybe_compression_level.level = - server_compression_level; + + void DisabledAlgorithmTest() { + Init(); + auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + auto s = test_.RequestCall(101); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage(std::string(1024, 'x')) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + test_.Expect(101, true); + test_.Expect(1, true); + test_.Step(); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + CoreEnd2endTest::IncomingCloseOnServer client_close; + test_.Expect(102, false); + s.NewBatch(103).RecvCloseOnServer(client_close); + test_.Expect(103, true); + test_.Step(); + // call was cancelled (closed) ... + EXPECT_NE(client_close.was_cancelled(), 0); + // with a certain error + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + // and we expect a specific reason for it + EXPECT_EQ(server_status.message(), + "Compression algorithm 'gzip' is disabled."); + EXPECT_EQ(s.method(), "/foo"); } - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(101), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - for (int i = 0; i < 2; i++) { - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - if (i > 0 || !send_message_before_initial_metadata) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = client_send_flags_bitmask; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); + + void RequestWithPayload( + uint32_t client_send_flags_bitmask, + std::initializer_list> + client_init_metadata) { + Init(); + auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata(client_init_metadata) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test_.RequestCall(100); + test_.Expect(100, true); + test_.Step(); + EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all()); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close); + for (int i = 0; i < 2; i++) { + c.NewBatch(2).SendMessage(std::string(1024, 'x'), + client_send_flags_bitmask); + test_.Expect(2, true); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + test_.Expect(102, true); + test_.Step(); + EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(client_message.payload(), std::string(1024, 'x')); + EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_); + s.NewBatch(103).SendMessage(std::string(1024, 'y')); + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(3).RecvMessage(server_message); + test_.Expect(103, true); + test_.Expect(3, true); + test_.Step(); + EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(server_message.payload(), std::string(1024, 'y')); + EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_); } + c.NewBatch(4).SendCloseFromClient(); + s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test_.Expect(1, true); + test_.Expect(4, true); + test_.Expect(101, true); + test_.Expect(104, true); + test_.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + } - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); - GPR_ASSERT(request_payload_recv->data.raw.compression == - (decompress_in_core ? GRPC_COMPRESS_NONE - : expected_algorithm_from_client)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - - GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); - if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { - const grpc_compression_algorithm algo_for_server_level = - grpc_call_compression_for_level(s, server_compression_level); - GPR_ASSERT( - response_payload_recv->data.raw.compression == - (decompress_in_core ? GRPC_COMPRESS_NONE : algo_for_server_level)); - } else { - GPR_ASSERT(response_payload_recv->data.raw.compression == - (decompress_in_core ? GRPC_COMPRESS_NONE - : expected_algorithm_from_server)); + void RequestWithSendMessageBeforeInitialMetadata() { + Init(); + auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + c.NewBatch(2).SendMessage(std::string(1024, 'x')); + test_.Expect(2, true); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test_.RequestCall(100); + test_.Expect(100, true); + test_.Step(); + EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all()); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close); + for (int i = 0; i < 2; i++) { + if (i > 0) { + c.NewBatch(2).SendMessage(std::string(1024, 'x')); + test_.Expect(2, true); + } + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + test_.Expect(102, true); + test_.Step(); + EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(client_message.payload(), std::string(1024, 'x')); + EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_); + s.NewBatch(103).SendMessage(std::string(1024, 'y')); + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(3).RecvMessage(server_message); + test_.Expect(103, true); + test_.Expect(3, true); + test_.Step(); + EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(server_message.payload(), std::string(1024, 'y')); + EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_); } + c.NewBatch(4).SendCloseFromClient(); + s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test_.Expect(1, true); + test_.Expect(4, true); + test_.Expect(101, true); + test_.Expect(104, true); + test_.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + } - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); + void RequestWithServerLevel(grpc_compression_level server_compression_level) { + Init(); + auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test_.RequestCall(100); + test_.Expect(100, true); + test_.Step(); + EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all()); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(101) + .SendInitialMetadata({}, 0, server_compression_level) + .RecvCloseOnServer(client_close); + for (int i = 0; i < 2; i++) { + c.NewBatch(2).SendMessage(std::string(1024, 'x')); + test_.Expect(2, true); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + test_.Expect(102, true); + test_.Step(); + EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(client_message.payload(), std::string(1024, 'x')); + EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_); + s.NewBatch(103).SendMessage(std::string(1024, 'y')); + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(3).RecvMessage(server_message); + test_.Expect(103, true); + test_.Expect(3, true); + test_.Step(); + EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW); + EXPECT_EQ(server_message.payload(), std::string(1024, 'y')); + EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_); + } + c.NewBatch(4).SendCloseFromClient(); + s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test_.Expect(1, true); + test_.Expect(4, true); + test_.Expect(101, true); + test_.Expect(104, true); + test_.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); + + private: + void Init() { + test_.InitClient(client_args_); + test_.InitServer(server_args_); + } + + CoreEnd2endTest& test_; + ChannelArgs client_args_ = ChannelArgs().Set( + GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE); + ChannelArgs server_args_ = ChannelArgs().Set( + GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE); + grpc_compression_algorithm expected_algorithm_from_client_ = + GRPC_COMPRESS_NONE; + grpc_compression_algorithm expected_algorithm_from_server_ = + GRPC_COMPRESS_NONE; +}; + +TEST_P(Http2SingleHopTest, DisabledAlgorithmDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP) + .DisabledAlgorithmTest(); +} + +TEST_P(Http2SingleHopTest, DisabledAlgorithmDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP) + .DecompressInApp() + .DisabledAlgorithmTest(); +} + +TEST_P(Http2SingleHopTest, + RequestWithExceptionallyUncompressedPayloadDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .RequestWithPayload(GRPC_WRITE_NO_COMPRESS, {}); +} + +TEST_P(Http2SingleHopTest, + RequestWithExceptionallyUncompressedPayloadDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .DecompressInApp() + .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP) + .RequestWithPayload(GRPC_WRITE_NO_COMPRESS, {}); +} + +TEST_P(Http2SingleHopTest, RequestWithUncompressedPayloadDecompressInCore) { + TestConfigurator(*this).RequestWithPayload(0, {}); +} + +TEST_P(Http2SingleHopTest, RequestWithUncompressedPayloadDecompressInApp) { + TestConfigurator(*this).DecompressInApp().RequestWithPayload(0, {}); +} + +TEST_P(Http2SingleHopTest, RequestWithCompressedPayloadDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .RequestWithPayload(0, {}); +} + +TEST_P(Http2SingleHopTest, RequestWithCompressedPayloadDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .DecompressInApp() + .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP) + .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP) + .RequestWithPayload(0, {}); +} + +TEST_P(Http2SingleHopTest, + RequestWithSendMessageBeforeInitialMetadataDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .RequestWithSendMessageBeforeInitialMetadata(); } -static void request_with_payload_template( - const CoreTestConfiguration& config, const char* test_name, - uint32_t client_send_flags_bitmask, - grpc_compression_algorithm default_client_channel_compression_algorithm, - grpc_compression_algorithm default_server_channel_compression_algorithm, - grpc_compression_algorithm expected_algorithm_from_client, - grpc_compression_algorithm expected_algorithm_from_server, - grpc_metadata* client_init_metadata, bool set_server_level, - grpc_compression_level server_compression_level, - bool send_message_before_initial_metadata) { - request_with_payload_template_inner( - config, test_name, client_send_flags_bitmask, - default_client_channel_compression_algorithm, - default_server_channel_compression_algorithm, - expected_algorithm_from_client, expected_algorithm_from_server, - client_init_metadata, set_server_level, server_compression_level, - send_message_before_initial_metadata, false); - request_with_payload_template_inner( - config, test_name, client_send_flags_bitmask, - default_client_channel_compression_algorithm, - default_server_channel_compression_algorithm, - expected_algorithm_from_client, expected_algorithm_from_server, - client_init_metadata, set_server_level, server_compression_level, - send_message_before_initial_metadata, true); +TEST_P(Http2SingleHopTest, + RequestWithSendMessageBeforeInitialMetadataDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP) + .DecompressInApp() + .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP) + .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP) + .RequestWithSendMessageBeforeInitialMetadata(); } -static void test_invoke_request_with_exceptionally_uncompressed_payload( - const CoreTestConfiguration& config) { - request_with_payload_template( - config, "test_invoke_request_with_exceptionally_uncompressed_payload", - GRPC_WRITE_NO_COMPRESS, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, nullptr, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, false); +TEST_P(Http2SingleHopTest, RequestWithServerLevelDecompressInCore) { + TestConfigurator(*this).RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH); } -static void test_invoke_request_with_uncompressed_payload( - const CoreTestConfiguration& config) { - request_with_payload_template( - config, "test_invoke_request_with_uncompressed_payload", 0, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, nullptr, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, false); +TEST_P(Http2SingleHopTest, RequestWithServerLevelDecompressInApp) { + TestConfigurator(*this) + .DecompressInApp() + .ExpectedAlgorithmFromServer(GRPC_COMPRESS_DEFLATE) + .RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH); } -static void test_invoke_request_with_compressed_payload( - const CoreTestConfiguration& config) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_GZIP, nullptr, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, false); +TEST_P(Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInCore) { + TestConfigurator(*this).RequestWithPayload( + 0, {{"grpc-internal-encoding-request", "gzip"}}); } -static void test_invoke_request_with_send_message_before_initial_metadata( - const CoreTestConfiguration& config) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_GZIP, nullptr, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, true); +TEST_P(Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInApp) { + TestConfigurator(*this) + .DecompressInApp() + .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP) + .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}}); } -static void test_invoke_request_with_server_level( - const CoreTestConfiguration& config) { - request_with_payload_template( - config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */, - nullptr, true, GRPC_COMPRESS_LEVEL_HIGH, false); +TEST_P( + Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE) + .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}}); } -static void test_invoke_request_with_compressed_payload_md_override( - const CoreTestConfiguration& config) { - grpc_metadata gzip_compression_override; - grpc_metadata identity_compression_override; - - gzip_compression_override.key = - grpc_slice_from_static_string("grpc-internal-encoding-request"); - gzip_compression_override.value = grpc_slice_from_static_string("gzip"); - memset(&gzip_compression_override.internal_data, 0, - sizeof(gzip_compression_override.internal_data)); - - identity_compression_override.key = - grpc_slice_from_static_string("grpc-internal-encoding-request"); - identity_compression_override.value = - grpc_slice_from_static_string("identity"); - memset(&identity_compression_override.internal_data, 0, - sizeof(identity_compression_override.internal_data)); - - // Channel default NONE (aka IDENTITY), call override to GZIP - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_1", 0, - GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); - - // Channel default DEFLATE, call override to GZIP - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_2", 0, - GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); - - // Channel default DEFLATE, call override to NONE (aka IDENTITY) - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload_md_override_3", 0, - GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, &identity_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false); +TEST_P( + Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE) + .DecompressInApp() + .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP) + .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}}); } -static void test_invoke_request_with_disabled_algorithm( - const CoreTestConfiguration& config) { - request_for_disabled_algorithm(config, - "test_invoke_request_with_disabled_algorithm", - 0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_STATUS_UNIMPLEMENTED, nullptr, false); - request_for_disabled_algorithm(config, - "test_invoke_request_with_disabled_algorithm", - 0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_STATUS_UNIMPLEMENTED, nullptr, true); +TEST_P( + Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInCore) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE) + .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}}); } -void compressed_payload(const CoreTestConfiguration& config) { - test_invoke_request_with_exceptionally_uncompressed_payload(config); - test_invoke_request_with_uncompressed_payload(config); - test_invoke_request_with_compressed_payload(config); - test_invoke_request_with_send_message_before_initial_metadata(config); - test_invoke_request_with_server_level(config); - test_invoke_request_with_compressed_payload_md_override(config); - test_invoke_request_with_disabled_algorithm(config); +TEST_P( + Http2SingleHopTest, + RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInApp) { + TestConfigurator(*this) + .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE) + .DecompressInApp() + .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}}); } -void compressed_payload_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/connectivity.cc b/test/core/end2end/tests/connectivity.cc index 02c89220de2..31f3842fd81 100644 --- a/test/core/end2end/tests/connectivity.cc +++ b/test/core/end2end/tests/connectivity.cc @@ -16,213 +16,73 @@ // // -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/thd.h" #include "src/core/lib/gprpp/time.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -typedef struct { - gpr_event started; - grpc_channel* channel; - grpc_completion_queue* cq; -} child_events; - -struct CallbackContext { - grpc_completion_queue_functor functor; - gpr_event finished; - explicit CallbackContext(void (*cb)(grpc_completion_queue_functor* functor, - int success)) { - functor.functor_run = cb; - functor.inlineable = false; - gpr_event_init(&finished); - } -}; - -static void child_thread(void* arg) { - child_events* ce = static_cast(arg); - grpc_event ev; - gpr_event_set(&ce->started, reinterpret_cast(1)); - gpr_log(GPR_DEBUG, "verifying"); - ev = grpc_completion_queue_next(ce->cq, gpr_inf_future(GPR_CLOCK_MONOTONIC), - nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == grpc_core::CqVerifier::tag(1)); - GPR_ASSERT(ev.success == 0); -} - -static void test_connectivity(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_connectivity_state state; - grpc_core::CqVerifier cqv(f->cq()); - child_events ce; - - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000); - - f->InitClient(client_args); - - ce.channel = f->client(); - ce.cq = f->cq(); - gpr_event_init(&ce.started); - grpc_core::Thread thd("grpc_connectivity", child_thread, &ce); - thd.Start(); - - gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); +namespace grpc_core { +namespace { +TEST_P(RetryHttp2Test, ConnectivityWatch) { + InitClient(ChannelArgs() + .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) + .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) + .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000)); // channels should start life in IDLE, and stay there - GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 0) == - GRPC_CHANNEL_IDLE); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); - GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 0) == - GRPC_CHANNEL_IDLE); - + EXPECT_EQ(CheckConnectivityState(false), GRPC_CHANNEL_IDLE); + Step(Duration::Milliseconds(100)); + EXPECT_EQ(CheckConnectivityState(false), GRPC_CHANNEL_IDLE); // start watching for a change - gpr_log(GPR_DEBUG, "watching"); - grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_IDLE, - gpr_now(GPR_CLOCK_MONOTONIC), f->cq(), - grpc_core::CqVerifier::tag(1)); - - // eventually the child thread completion should trigger - thd.Join(); - + WatchConnectivityState(GRPC_CHANNEL_IDLE, Duration::Milliseconds(500), 1); + Expect(1, false); + Step(Duration::Minutes(1)); // check that we're still in idle, and start connecting - GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 1) == - GRPC_CHANNEL_IDLE); + EXPECT_EQ(CheckConnectivityState(true), GRPC_CHANNEL_IDLE); // start watching for a change - grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_IDLE, - grpc_timeout_seconds_to_deadline(10), - f->cq(), grpc_core::CqVerifier::tag(2)); - + WatchConnectivityState(GRPC_CHANNEL_IDLE, Duration::Seconds(10), 2); // and now the watch should trigger - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING); - + Expect(2, true); + Step(); + grpc_connectivity_state state = CheckConnectivityState(false); + EXPECT_THAT(state, ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_CHANNEL_CONNECTING)); // quickly followed by a transition to TRANSIENT_FAILURE - grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_CONNECTING, - grpc_timeout_seconds_to_deadline(10), - f->cq(), grpc_core::CqVerifier::tag(3)); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING); - - gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); - + WatchConnectivityState(GRPC_CHANNEL_CONNECTING, Duration::Seconds(10), 3); + Expect(3, true); + Step(); + state = CheckConnectivityState(false); + EXPECT_THAT(state, ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_CHANNEL_CONNECTING)); // now let's bring up a server to connect to - f->InitServer(grpc_core::ChannelArgs()); - - gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); - + InitServer(ChannelArgs()); // we'll go through some set of transitions (some might be missed), until // READY is reached while (state != GRPC_CHANNEL_READY) { - grpc_channel_watch_connectivity_state( - f->client(), state, grpc_timeout_seconds_to_deadline(10), f->cq(), - grpc_core::CqVerifier::tag(4)); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(grpc_core::Duration::Seconds(20)); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_READY || - state == GRPC_CHANNEL_CONNECTING || - state == GRPC_CHANNEL_TRANSIENT_FAILURE); + WatchConnectivityState(state, Duration::Seconds(10), 4); + Expect(4, true); + Step(Duration::Seconds(20)); + state = CheckConnectivityState(false); + EXPECT_THAT(state, + ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_READY)); } - // bring down the server again // we should go immediately to TRANSIENT_FAILURE - gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); - - grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_READY, - grpc_timeout_seconds_to_deadline(10), - f->cq(), grpc_core::CqVerifier::tag(5)); - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - - cqv.Expect(grpc_core::CqVerifier::tag(5), true); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); -} - -static void cb_watch_connectivity(grpc_completion_queue_functor* functor, - int success) { - CallbackContext* cb_ctx = reinterpret_cast(functor); - - gpr_log(GPR_DEBUG, "cb_watch_connectivity called, verifying"); - - // callback must not have errors - GPR_ASSERT(success != 0); - - gpr_event_set(&cb_ctx->finished, reinterpret_cast(1)); -} - -static void cb_shutdown(grpc_completion_queue_functor* functor, - int /*success*/) { - CallbackContext* cb_ctx = reinterpret_cast(functor); - - gpr_log(GPR_DEBUG, "cb_shutdown called, nothing to do"); - gpr_event_set(&cb_ctx->finished, reinterpret_cast(1)); -} - -static void test_watch_connectivity_cq_callback( - const CoreTestConfiguration& config) { - CallbackContext cb_ctx(cb_watch_connectivity); - CallbackContext cb_shutdown_ctx(cb_shutdown); - grpc_completion_queue* cq; - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - - f->InitClient(grpc_core::ChannelArgs()); - - // start connecting - grpc_channel_check_connectivity_state(f->client(), 1); - - // create the cq callback - cq = grpc_completion_queue_create_for_callback(&cb_shutdown_ctx.functor, - nullptr); - - // start watching for any change, cb is immediately called - // and no dead lock should be raised - grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_IDLE, - grpc_timeout_seconds_to_deadline(3), cq, - &cb_ctx.functor); - - // we just check that the callback was executed once notifying a connection - // transition - GPR_ASSERT(gpr_event_wait(&cb_ctx.finished, - gpr_inf_future(GPR_CLOCK_MONOTONIC)) != nullptr); - - // shutdown, since shutdown cb might be executed in a background thread - // we actively wait till is executed. - grpc_completion_queue_shutdown(cq); - gpr_event_wait(&cb_shutdown_ctx.finished, - gpr_inf_future(GPR_CLOCK_MONOTONIC)); - grpc_completion_queue_destroy(cq); -} - -void connectivity(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_connectivity(config); - test_watch_connectivity_cq_callback(config); + WatchConnectivityState(GRPC_CHANNEL_READY, Duration::Seconds(10), 5); + ShutdownServerAndNotify(1000); + Expect(5, true); + Expect(1000, true); + Step(); + state = CheckConnectivityState(false); + EXPECT_THAT(state, + ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_IDLE)); } -void connectivity_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/default_host.cc b/test/core/end2end/tests/default_host.cc index 28f3c779cd2..bd29654b3d6 100644 --- a/test/core/end2end/tests/default_host.cc +++ b/test/core/end2end/tests/default_host.cc @@ -16,164 +16,55 @@ // // -#include +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - return f; -} - -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(error == GRPC_CALL_OK); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(error == GRPC_CALL_OK); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(error == GRPC_CALL_OK); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - - if (config.overridden_call_host != nullptr) { - validate_host_override_string(config.overridden_call_host, - call_details.host, config); +using testing::AnyOf; +using testing::StartsWith; + +namespace grpc_core { +namespace { + +TEST_P(CoreClientChannelTest, DefaultHost) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + if (GetParam()->overridden_call_host != nullptr) { + EXPECT_EQ(GetParam()->overridden_call_host, s.host()); } else { - GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9) || - grpc_slice_buf_start_eq(call_details.host, "127.0.0.1", 9)); + EXPECT_THAT(s.host(), AnyOf(StartsWith("localhost"), + StartsWith("127.0.0.1"), StartsWith("[::1]"))); } - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void default_host(const CoreTestConfiguration& config) { - test_invoke_simple_request(config); + EXPECT_FALSE(client_close.was_cancelled()); } -void default_host_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/disappearing_server.cc b/test/core/end2end/tests/disappearing_server.cc index f8783c23426..36847afcffb 100644 --- a/test/core/end2end/tests/disappearing_server.cc +++ b/test/core/end2end/tests/disappearing_server.cc @@ -16,117 +16,41 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static void do_request_and_shutdown_server( - const CoreTestConfiguration& /*config*/, CoreTestFixture* f, - grpc_core::CqVerifier& cqv) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - // should be able to shut down the server early - // - and still complete the request - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(1000)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(1000), true); - cqv.Verify(); +#ifndef GPR_WINDOWS // b/148110727 for more details +namespace grpc_core { + +static void OneRequestAndShutdownServer(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + CoreEnd2endTest::IncomingMetadata server_initial_md; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_md) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + test.ShutdownServerAndNotify(1000); + CoreEnd2endTest::IncomingCloseOnServer client_closed; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_closed); + test.Expect(102, true); + test.Expect(1, true); + test.Expect(1000, true); + test.Step(); // Please refer https://github.com/grpc/grpc/issues/21221 for additional // details. // TODO(yashykt@) - The following line should be removeable after C-Core @@ -134,47 +58,19 @@ static void do_request_and_shutdown_server( // test remains flaky even after this, an alternative fix would be to send a // request when the server is in the shut down state. // - cqv.VerifyEmpty(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); + test.Step(); - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_closed.was_cancelled()); } -static void disappearing_server_test(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_core::CqVerifier cqv(f->cq()); - - gpr_log(GPR_INFO, "Running test: %s/%s", "disappearing_server_test", - config.name); - - f->InitClient(grpc_core::ChannelArgs()); - f->InitServer(grpc_core::ChannelArgs()); - - do_request_and_shutdown_server(config, f.get(), cqv); - - // now destroy and recreate the server - f->InitServer(grpc_core::ChannelArgs()); - - do_request_and_shutdown_server(config, f.get(), cqv); +TEST_P(CoreClientChannelTest, DisappearingServer) { + OneRequestAndShutdownServer(*this); + InitServer(ChannelArgs()); + OneRequestAndShutdownServer(*this); } -void disappearing_server(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); -#ifndef GPR_WINDOWS // b/148110727 for more details - disappearing_server_test(config); +} // namespace grpc_core #endif // GPR_WINDOWS -} - -void disappearing_server_pre_init(void) {} diff --git a/test/core/end2end/tests/empty_batch.cc b/test/core/end2end/tests/empty_batch.cc index de459b70392..046d6d44b71 100644 --- a/test/core/end2end/tests/empty_batch.cc +++ b/test/core/end2end/tests/empty_batch.cc @@ -16,60 +16,17 @@ // // -#include -#include +#include "gtest/gtest.h" -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void empty_batch_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_core::CqVerifier cqv(f->cq()); - grpc_call_error error; - grpc_op* op = nullptr; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - error = - grpc_call_start_batch(c, op, 0, grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - grpc_call_unref(c); -} - -static void test_invoke_empty_body(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_empty_body", nullptr, nullptr); - empty_batch_body(config, f.get()); -} +namespace grpc_core { -void empty_batch(const CoreTestConfiguration& config) { - test_invoke_empty_body(config); +TEST_P(CoreEnd2endTest, EmptyBatch) { + auto c = NewClientCall("/service/method").Create(); + c.NewBatch(1); + Expect(1, true); + Step(); } -void empty_batch_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc index 0ad69dc3741..4583512d83c 100644 --- a/test/core/end2end/tests/filter_causes_close.cc +++ b/test/core/end2end/tests/filter_causes_close.cc @@ -17,137 +17,27 @@ // #include -#include - -#include -#include #include "absl/status/status.h" +#include "gtest/gtest.h" -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -// Simple request via a server filter that always closes the stream. -static void test_request(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = begin_test(config, "filter_causes_close", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == - grpc_slice_str_cmp(details, "Failure that's not preventable.")); - - f->ShutdownServer(); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} +namespace grpc_core { +namespace { //****************************************************************************** // Test filter - always closes incoming requests @@ -161,19 +51,19 @@ typedef struct { uint8_t unused; } channel_data; -static void recv_im_ready(void* arg, grpc_error_handle error) { +void recv_im_ready(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); - grpc_core::Closure::Run( + Closure::Run( DEBUG_LOCATION, calld->recv_im_ready, grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING( "Failure that's not preventable.", &error, 1), - grpc_core::StatusIntProperty::kRpcStatus, + StatusIntProperty::kRpcStatus, GRPC_STATUS_PERMISSION_DENIED)); } -static void start_transport_stream_op_batch( - grpc_call_element* elem, grpc_transport_stream_op_batch* op) { +void start_transport_stream_op_batch(grpc_call_element* elem, + grpc_transport_stream_op_batch* op) { call_data* calld = static_cast(elem->call_data); if (op->recv_initial_metadata) { calld->recv_im_ready = @@ -184,23 +74,23 @@ static void start_transport_stream_op_batch( grpc_call_next_op(elem, op); } -static grpc_error_handle init_call_elem( - grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { +grpc_error_handle init_call_elem(grpc_call_element* /*elem*/, + const grpc_call_element_args* /*args*/) { return absl::OkStatus(); } -static void destroy_call_elem(grpc_call_element* /*elem*/, - const grpc_call_final_info* /*final_info*/, - grpc_closure* /*ignored*/) {} +void destroy_call_elem(grpc_call_element* /*elem*/, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*ignored*/) {} -static grpc_error_handle init_channel_elem( - grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { +grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return absl::OkStatus(); } -static void destroy_channel_elem(grpc_channel_element* /*elem*/) {} +void destroy_channel_elem(grpc_channel_element* /*elem*/) {} -static const grpc_channel_filter test_filter = { +const grpc_channel_filter test_filter = { start_transport_stream_op_batch, nullptr, grpc_channel_next_op, @@ -215,22 +105,29 @@ static const grpc_channel_filter test_filter = { grpc_channel_next_get_info, "filter_causes_close"}; -//****************************************************************************** -// Registration -// - -void filter_causes_close(const CoreTestConfiguration& config) { - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage( - GRPC_SERVER_CHANNEL, 0, - [](grpc_core::ChannelStackBuilder* builder) { - builder->PrependFilter(&test_filter); - return true; - }); - }, - [config] { test_request(config); }); +TEST_P(CoreEnd2endTest, FilterCausesClose) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + GRPC_SERVER_CHANNEL, 0, [](ChannelStackBuilder* builder) { + builder->PrependFilter(&test_filter); + return true; + }); + }); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "Failure that's not preventable."); } -void filter_causes_close_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/filter_context.cc b/test/core/end2end/tests/filter_context.cc index d59bec91a97..83c17ef991e 100644 --- a/test/core/end2end/tests/filter_context.cc +++ b/test/core/end2end/tests/filter_context.cc @@ -17,169 +17,31 @@ // #include -#include #include -#include #include -#include #include #include "absl/status/status.h" +#include "gtest/gtest.h" -#include -#include -#include -#include #include #include -#include -#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -enum { TIMEOUT = 200000 }; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Simple request to test that filters see a consistent view of the -// call context. -static void test_request(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = begin_test(config, "filter_context", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_string = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(s); - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} +namespace grpc_core { +namespace { //****************************************************************************** // Test context filter @@ -189,16 +51,16 @@ struct call_data { grpc_call_context_element* context; }; -static grpc_error_handle init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +grpc_error_handle init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { call_data* calld = static_cast(elem->call_data); calld->context = args->context; gpr_log(GPR_INFO, "init_call_elem(): context=%p", args->context); return absl::OkStatus(); } -static void start_transport_stream_op_batch( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { +void start_transport_stream_op_batch(grpc_call_element* elem, + grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); // If batch payload context is not null (which will happen in some // cancellation cases), make sure we get the same context here that we @@ -211,18 +73,18 @@ static void start_transport_stream_op_batch( grpc_call_next_op(elem, batch); } -static void destroy_call_elem(grpc_call_element* /*elem*/, - const grpc_call_final_info* /*final_info*/, - grpc_closure* /*ignored*/) {} +void destroy_call_elem(grpc_call_element* /*elem*/, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*ignored*/) {} -static grpc_error_handle init_channel_elem( - grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { +grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return absl::OkStatus(); } -static void destroy_channel_elem(grpc_channel_element* /*elem*/) {} +void destroy_channel_elem(grpc_channel_element* /*elem*/) {} -static const grpc_channel_filter test_filter = { +const grpc_channel_filter test_filter = { start_transport_stream_op_batch, nullptr, grpc_channel_next_op, @@ -237,31 +99,49 @@ static const grpc_channel_filter test_filter = { grpc_channel_next_get_info, "filter_context"}; -//****************************************************************************** -// Registration -// - -void filter_context(const CoreTestConfiguration& config) { - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL, - GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) { - builder->channel_init()->RegisterStage( - type, INT_MAX, [](grpc_core::ChannelStackBuilder* builder) { - // Want to add the filter as close to the end as possible, to - // make sure that all of the filters work well together. - // However, we can't add it at the very end, because the - // connected channel filter must be the last one. So we add it - // right before the last one. - auto it = builder->mutable_stack()->end(); - --it; - builder->mutable_stack()->insert(it, &test_filter); - return true; - }); - } - }, - [config] { test_request(config); }); +// Simple request to test that filters see a consistent view of the +// call context. +TEST_P(CoreEnd2endTest, FilterContext) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL, + GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) { + builder->channel_init()->RegisterStage( + type, INT_MAX, [](ChannelStackBuilder* builder) { + // Want to add the filter as close to the end as possible, to + // make sure that all of the filters work well together. + // However, we can't add it at the very end, because the + // connected channel filter must be the last one. So we add it + // right before the last one. + auto it = builder->mutable_stack()->end(); + --it; + builder->mutable_stack()->insert(it, &test_filter); + return true; + }); + } + }); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -void filter_context_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/filter_init_fails.cc b/test/core/end2end/tests/filter_init_fails.cc index 753d7cd7294..44f6b832d6b 100644 --- a/test/core/end2end/tests/filter_init_fails.cc +++ b/test/core/end2end/tests/filter_init_fails.cc @@ -17,22 +17,17 @@ // #include -#include #include -#include #include #include #include "absl/status/status.h" +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" -#include -#include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" @@ -40,371 +35,52 @@ #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/promise/arena_promise.h" #include "src/core/lib/promise/promise.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -enum { TIMEOUT = 200000 }; +using ::testing::AnyOf; -static bool g_enable_server_channel_filter = false; -static bool g_enable_client_channel_filter = false; -static bool g_enable_client_subchannel_filter = false; -static bool g_channel_filter_init_failure = false; +namespace grpc_core { +namespace { -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Simple request via a SERVER_CHANNEL filter that always fails to -// initialize the call. -static void test_server_channel_filter(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = begin_test(config, "filter_init_fails", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - if (g_channel_filter_init_failure) { - // Inproc channel returns invalid_argument and other clients return - // unavailable. - // Windows with sockpair returns unknown. - GPR_ASSERT(status == GRPC_STATUS_UNKNOWN || - status == GRPC_STATUS_UNAVAILABLE || - status == GRPC_STATUS_INVALID_ARGUMENT); - } else { - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - } - - f->ShutdownServer(); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} - -// Simple request via a CLIENT_CHANNEL or CLIENT_DIRECT_CHANNEL filter -// that always fails to initialize the call. -static void test_client_channel_filter(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - auto f = begin_test(config, "filter_init_fails", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - if (g_channel_filter_init_failure) { - GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); - } else { - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - } - - f->ShutdownServer(); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} - -// Simple request via a CLIENT_SUBCHANNEL filter that always fails to -// initialize the call. -static void test_client_subchannel_filter(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - auto f = begin_test(config, "filter_init_fails", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - if (g_channel_filter_init_failure) { - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - } else { - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - } - - // Reset and create a new call. (The first call uses a different code - // path in client_channel.c than subsequent calls on the same channel, - // and we need to test both.) - grpc_call_unref(c); - status = GRPC_STATUS_OK; - grpc_slice_unref(details); - details = grpc_empty_slice(); - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - if (g_channel_filter_init_failure) { - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - } else { - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "access denied")); - } - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} - -//****************************************************************************** +// // Test filter - always fails to initialize a call // -static grpc_error_handle init_call_elem( - grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { +grpc_error_handle init_call_elem(grpc_call_element* /*elem*/, + const grpc_call_element_args* /*args*/) { return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"), - grpc_core::StatusIntProperty::kRpcStatus, + StatusIntProperty::kRpcStatus, GRPC_STATUS_PERMISSION_DENIED); } -static void destroy_call_elem(grpc_call_element* /*elem*/, - const grpc_call_final_info* /*final_info*/, - grpc_closure* /*ignored*/) {} +void destroy_call_elem(grpc_call_element* /*elem*/, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*ignored*/) {} -static grpc_error_handle init_channel_elem( - grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { - if (g_channel_filter_init_failure) { +grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/, + grpc_channel_element_args* args) { + if (args->channel_args.GetBool("channel_init_fails").value_or(false)) { return grpc_error_set_int( GRPC_ERROR_CREATE("Test channel filter init error"), - grpc_core::StatusIntProperty::kRpcStatus, GRPC_STATUS_INVALID_ARGUMENT); + StatusIntProperty::kRpcStatus, GRPC_STATUS_INVALID_ARGUMENT); } return absl::OkStatus(); } -static void destroy_channel_elem(grpc_channel_element* /*elem*/) {} +void destroy_channel_elem(grpc_channel_element* /*elem*/) {} -static const grpc_channel_filter test_filter = { +const grpc_channel_filter test_filter = { grpc_call_next_op, - [](grpc_channel_element*, grpc_core::CallArgs, - grpc_core::NextPromiseFactory) - -> grpc_core::ArenaPromise { - return grpc_core::Immediate(grpc_core::ServerMetadataFromStatus( + [](grpc_channel_element*, CallArgs, + NextPromiseFactory) -> ArenaPromise { + return Immediate(ServerMetadataFromStatus( absl::PermissionDeniedError("access denied"))); }, grpc_channel_next_op, @@ -419,63 +95,175 @@ static const grpc_channel_filter test_filter = { grpc_channel_next_get_info, "filter_init_fails"}; -//****************************************************************************** -// Registration -// +void RegisterFilter(grpc_channel_stack_type type) { + CoreConfiguration::RegisterBuilder( + [type](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + type, INT_MAX, [](ChannelStackBuilder* builder) { + // Want to add the filter as close to the end as possible, + // to make sure that all of the filters work well together. + // However, we can't add it at the very end, because either the + // client_channel filter or connected_channel filter must be the + // last one. So we add it right before the last one. + auto it = builder->mutable_stack()->end(); + --it; + builder->mutable_stack()->insert(it, &test_filter); + return true; + }); + }); +} -static void filter_init_fails_internal(const CoreTestConfiguration& config) { - gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter."); - g_enable_server_channel_filter = true; - test_server_channel_filter(config); - g_enable_server_channel_filter = false; - gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter."); - g_enable_client_channel_filter = true; - test_client_channel_filter(config); - g_enable_client_channel_filter = false; - // If the client handshake completes before the server handshake and the - // client is able to send application data before the server handshake - // completes, then testing the CLIENT_SUBCHANNEL filter will cause the server - // to freeze waiting for the final handshake message from the client. This - // handshake message will never arrive because it would have been sent with - // the first application data message, which failed because of the filter. - if ((config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) && - !(config.feature_mask & - FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST)) { - gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); - g_enable_client_subchannel_filter = true; - test_client_subchannel_filter(config); - g_enable_client_subchannel_filter = false; - } +TEST_P(CoreEnd2endTest, DISABLED_ServerFilterChannelInitFails) { + RegisterFilter(GRPC_SERVER_CHANNEL); + InitClient(ChannelArgs()); + InitServer(ChannelArgs().Set("channel_init_fails", true)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(1, true); + Step(); + // Inproc channel returns invalid_argument and other clients return + // unavailable. + // Windows with sockpair returns unknown. + EXPECT_THAT(server_status.status(), + AnyOf(GRPC_STATUS_UNKNOWN, GRPC_STATUS_UNAVAILABLE, + GRPC_STATUS_INVALID_ARGUMENT)); + ShutdownAndDestroyServer(); +}; + +TEST_P(CoreEnd2endTest, ServerFilterCallInitFails) { + RegisterFilter(GRPC_SERVER_CHANNEL); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "access denied"); + ShutdownAndDestroyServer(); +}; + +TEST_P(CoreEnd2endTest, DISABLED_ClientFilterChannelInitFails) { + RegisterFilter(GRPC_CLIENT_CHANNEL); + RegisterFilter(GRPC_CLIENT_DIRECT_CHANNEL); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set("channel_init_fails", true)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_INVALID_ARGUMENT); +} + +TEST_P(CoreEnd2endTest, ClientFilterCallInitFails) { + RegisterFilter(GRPC_CLIENT_CHANNEL); + RegisterFilter(GRPC_CLIENT_DIRECT_CHANNEL); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "access denied"); +} + +TEST_P(CoreClientChannelTest, DISABLED_SubchannelFilterChannelInitFails) { + RegisterFilter(GRPC_CLIENT_SUBCHANNEL); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set("channel_init_fails", true)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + // Create a new call. (The first call uses a different code path in + // client_channel.c than subsequent calls on the same channel, and we need to + // test both.) + auto c2 = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status2; + CoreEnd2endTest::IncomingMetadata server_initial_metadata2; + CoreEnd2endTest::IncomingMessage server_message2; + c2.NewBatch(2) + .SendInitialMetadata({}) + .SendMessage("hi again") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata2) + .RecvStatusOnClient(server_status2); + Expect(2, true); + Step(); + EXPECT_EQ(server_status2.status(), GRPC_STATUS_UNAVAILABLE); } -void filter_init_fails(const CoreTestConfiguration& config) { - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - auto register_stage = [builder](grpc_channel_stack_type type, - bool* enable) { - builder->channel_init()->RegisterStage( - type, INT_MAX, [enable](grpc_core::ChannelStackBuilder* builder) { - if (!*enable) return true; - // Want to add the filter as close to the end as possible, - // to make sure that all of the filters work well together. - // However, we can't add it at the very end, because either the - // client_channel filter or connected_channel filter must be the - // last one. So we add it right before the last one. - auto it = builder->mutable_stack()->end(); - --it; - builder->mutable_stack()->insert(it, &test_filter); - return true; - }); - }; - register_stage(GRPC_SERVER_CHANNEL, &g_enable_server_channel_filter); - register_stage(GRPC_CLIENT_CHANNEL, &g_enable_client_channel_filter); - register_stage(GRPC_CLIENT_SUBCHANNEL, - &g_enable_client_subchannel_filter); - register_stage(GRPC_CLIENT_DIRECT_CHANNEL, - &g_enable_client_channel_filter); - }, - [&config] { filter_init_fails_internal(config); }); +TEST_P(CoreClientChannelTest, SubchannelFilterCallInitFails) { + RegisterFilter(GRPC_CLIENT_SUBCHANNEL); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "access denied"); + // Create a new call. (The first call uses a different code path in + // client_channel.c than subsequent calls on the same channel, and we need to + // test both.) + auto c2 = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status2; + CoreEnd2endTest::IncomingMetadata server_initial_metadata2; + CoreEnd2endTest::IncomingMessage server_message2; + c2.NewBatch(2) + .SendInitialMetadata({}) + .SendMessage("hi again") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata2) + .RecvStatusOnClient(server_status2); + Expect(2, true); + Step(); + EXPECT_EQ(server_status2.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status2.message(), "access denied"); } -void filter_init_fails_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc deleted file mode 100644 index b04121dca72..00000000000 --- a/test/core/end2end/tests/filter_latency.cc +++ /dev/null @@ -1,289 +0,0 @@ -// -// -// Copyright 2016 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 -#include - -#include -#include -#include -#include - -#include "absl/status/status.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/channel_fwd.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/surface/channel_stack_type.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -enum { TIMEOUT = 200000 }; - -static gpr_mu g_mu; -static gpr_timespec g_client_latency; -static gpr_timespec g_server_latency; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Simple request via a server filter that saves the reported latency value. -static void test_request(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = begin_test(config, "filter_latency", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_mu_lock(&g_mu); - g_client_latency = gpr_time_0(GPR_TIMESPAN); - g_server_latency = gpr_time_0(GPR_TIMESPAN); - gpr_mu_unlock(&g_mu); - const gpr_timespec start_time = gpr_now(GPR_CLOCK_REALTIME); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_string = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(s); - grpc_call_unref(c); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - const gpr_timespec end_time = gpr_now(GPR_CLOCK_REALTIME); - const gpr_timespec max_latency = gpr_time_sub(end_time, start_time); - - // Perform checks after test tear-down - // Guards against the case that there's outstanding channel-related work on a - // call prior to verification - gpr_mu_lock(&g_mu); - GPR_ASSERT(gpr_time_cmp(max_latency, g_client_latency) >= 0); - GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_client_latency) <= 0); - GPR_ASSERT(gpr_time_cmp(max_latency, g_server_latency) >= 0); - GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_server_latency) <= 0); - // Server latency should always be smaller than client latency, however since - // we only calculate latency at destruction time, and that might mean that we - // need to wait for outstanding channel-related work, this isn't verifiable - // right now (the server MAY hold on to the call for longer than the client). - // GPR_ASSERT(gpr_time_cmp(g_server_latency, g_client_latency) < 0); - gpr_mu_unlock(&g_mu); -} - -//****************************************************************************** -// Test latency filter -// - -static grpc_error_handle init_call_elem( - grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { - return absl::OkStatus(); -} - -static void client_destroy_call_elem(grpc_call_element* /*elem*/, - const grpc_call_final_info* final_info, - grpc_closure* /*ignored*/) { - gpr_mu_lock(&g_mu); - g_client_latency = final_info->stats.latency; - gpr_mu_unlock(&g_mu); -} - -static void server_destroy_call_elem(grpc_call_element* /*elem*/, - const grpc_call_final_info* final_info, - grpc_closure* /*ignored*/) { - gpr_mu_lock(&g_mu); - g_server_latency = final_info->stats.latency; - gpr_mu_unlock(&g_mu); -} - -static grpc_error_handle init_channel_elem( - grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { - return absl::OkStatus(); -} - -static void destroy_channel_elem(grpc_channel_element* /*elem*/) {} - -static const grpc_channel_filter test_client_filter = { - grpc_call_next_op, nullptr, - grpc_channel_next_op, 0, - init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, - client_destroy_call_elem, 0, - init_channel_elem, grpc_channel_stack_no_post_init, - destroy_channel_elem, grpc_channel_next_get_info, - "client_filter_latency"}; - -static const grpc_channel_filter test_server_filter = { - grpc_call_next_op, nullptr, - grpc_channel_next_op, 0, - init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, - server_destroy_call_elem, 0, - init_channel_elem, grpc_channel_stack_no_post_init, - destroy_channel_elem, grpc_channel_next_get_info, - "server_filter_latency"}; - -//****************************************************************************** -// Registration -// - -void filter_latency(const CoreTestConfiguration& config) { - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - auto register_stage = [builder](grpc_channel_stack_type type, - const grpc_channel_filter* filter) { - builder->channel_init()->RegisterStage( - type, INT_MAX, [filter](grpc_core::ChannelStackBuilder* builder) { - // Want to add the filter as close to the end as possible, to - // make sure that all of the filters work well together. - // However, we can't add it at the very end, because the - // connected channel filter must be the last one. So we add it - // right before the last one. - auto it = builder->mutable_stack()->end(); - --it; - builder->mutable_stack()->insert(it, filter); - return true; - }); - }; - register_stage(GRPC_CLIENT_CHANNEL, &test_client_filter); - register_stage(GRPC_CLIENT_DIRECT_CHANNEL, &test_client_filter); - register_stage(GRPC_SERVER_CHANNEL, &test_server_filter); - }, - [config] { test_request(config); }); -} - -void filter_latency_pre_init(void) { gpr_mu_init(&g_mu); } diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc deleted file mode 100644 index 89e8f65b7b0..00000000000 --- a/test/core/end2end/tests/filter_status_code.cc +++ /dev/null @@ -1,353 +0,0 @@ -// -// -// Copyright 2017 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. -// -// - -// This test verifies - -// 1) grpc_call_final_info passed to the filters on destroying a call contains -// the proper status. -// 2) If the response has both an HTTP status code and a gRPC status code, then -// we should prefer the gRPC status code as mentioned in -// https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md -// - -#include -#include - -#include -#include -#include -#include - -#include "absl/status/status.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/channel/channel_fwd.h" -#include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/channel/channel_stack_builder.h" -#include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/error.h" -#include "src/core/lib/surface/call.h" -#include "src/core/lib/surface/channel_stack_type.h" -#include "src/core/lib/transport/metadata_batch.h" -#include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static gpr_mu g_mu; -static grpc_call_stack* g_client_call_stack; -static grpc_call_stack* g_server_call_stack; -static bool g_client_code_recv; -static bool g_server_code_recv; -static gpr_cv g_client_code_cv; -static gpr_cv g_server_code_cv; -static grpc_status_code g_client_status_code; -static grpc_status_code g_server_status_code; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Simple request via a server filter that saves the reported status code. -static void test_request(const CoreTestConfiguration& config) { - g_client_code_recv = false; - g_server_code_recv = false; - - grpc_call* c; - grpc_call* s; - auto f = begin_test(config, "filter_status_code", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_mu_lock(&g_mu); - g_client_call_stack = nullptr; - g_server_call_stack = nullptr; - g_client_status_code = GRPC_STATUS_OK; - g_server_status_code = GRPC_STATUS_OK; - gpr_mu_unlock(&g_mu); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - gpr_mu_lock(&g_mu); - g_client_call_stack = grpc_call_get_call_stack(c); - gpr_mu_unlock(&g_mu); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - gpr_mu_lock(&g_mu); - g_server_call_stack = grpc_call_get_call_stack(s); - gpr_mu_unlock(&g_mu); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_string = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_string; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(s); - grpc_call_unref(c); - - // Perform checks after test tear-down - // Guards against the case that there's outstanding channel-related work on a - // call prior to verification - gpr_mu_lock(&g_mu); - if (!g_client_code_recv) { - GPR_ASSERT(gpr_cv_wait(&g_client_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3)) == 0); - } - if (!g_server_code_recv) { - GPR_ASSERT(gpr_cv_wait(&g_server_code_cv, &g_mu, - grpc_timeout_seconds_to_deadline(3)) == 0); - } - GPR_ASSERT(g_client_status_code == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(g_server_status_code == GRPC_STATUS_UNIMPLEMENTED); - gpr_mu_unlock(&g_mu); -} - -//****************************************************************************** -// Test status_code filter -// - -typedef struct final_status_data { - grpc_call_stack* call; -} final_status_data; - -static void server_start_transport_stream_op_batch( - grpc_call_element* elem, grpc_transport_stream_op_batch* op) { - auto* data = static_cast(elem->call_data); - gpr_mu_lock(&g_mu); - if (data->call == g_server_call_stack) { - if (op->send_initial_metadata) { - auto* batch = op->payload->send_initial_metadata.send_initial_metadata; - auto* status = batch->get_pointer(grpc_core::HttpStatusMetadata()); - if (status != nullptr) { - // Replace the HTTP status with 404 - *status = 404; - } - } - } - gpr_mu_unlock(&g_mu); - grpc_call_next_op(elem, op); -} - -static grpc_error_handle init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { - final_status_data* data = static_cast(elem->call_data); - data->call = args->call_stack; - return absl::OkStatus(); -} - -static void client_destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* /*ignored*/) { - final_status_data* data = static_cast(elem->call_data); - gpr_mu_lock(&g_mu); - // Some fixtures, like proxies, will spawn intermidiate calls - // We only want the results from our explicit calls - if (data->call == g_client_call_stack) { - g_client_status_code = final_info->final_status; - g_client_code_recv = true; - gpr_cv_signal(&g_client_code_cv); - } - gpr_mu_unlock(&g_mu); -} - -static void server_destroy_call_elem(grpc_call_element* elem, - const grpc_call_final_info* final_info, - grpc_closure* /*ignored*/) { - final_status_data* data = static_cast(elem->call_data); - gpr_mu_lock(&g_mu); - // Some fixtures, like proxies, will spawn intermidiate calls - // We only want the results from our explicit calls - if (data->call == g_server_call_stack) { - g_server_status_code = final_info->final_status; - g_server_code_recv = true; - gpr_cv_signal(&g_server_code_cv); - } - gpr_mu_unlock(&g_mu); -} - -static grpc_error_handle init_channel_elem( - grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { - return absl::OkStatus(); -} - -static void destroy_channel_elem(grpc_channel_element* /*elem*/) {} - -static const grpc_channel_filter test_client_filter = { - grpc_call_next_op, - nullptr, - grpc_channel_next_op, - sizeof(final_status_data), - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - client_destroy_call_elem, - 0, - init_channel_elem, - grpc_channel_stack_no_post_init, - destroy_channel_elem, - grpc_channel_next_get_info, - "client_filter_status_code"}; - -static const grpc_channel_filter test_server_filter = { - server_start_transport_stream_op_batch, - nullptr, - grpc_channel_next_op, - sizeof(final_status_data), - init_call_elem, - grpc_call_stack_ignore_set_pollset_or_pollset_set, - server_destroy_call_elem, - 0, - init_channel_elem, - grpc_channel_stack_no_post_init, - destroy_channel_elem, - grpc_channel_next_get_info, - "server_filter_status_code"}; - -//****************************************************************************** -// Registration -// - -void filter_status_code(const CoreTestConfiguration& config) { - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - auto register_stage = [builder](grpc_channel_stack_type type, - const grpc_channel_filter* filter) { - builder->channel_init()->RegisterStage( - type, INT_MAX, [filter](grpc_core::ChannelStackBuilder* builder) { - // Want to add the filter as close to the end as possible, to - // make sure that all of the filters work well together. - // However, we can't add it at the very end, because the - // connected_channel/client_channel filter must be the last one. - // So we add it right before the last one. - auto it = builder->mutable_stack()->end(); - --it; - builder->mutable_stack()->insert(it, filter); - return true; - }); - }; - register_stage(GRPC_CLIENT_CHANNEL, &test_client_filter); - register_stage(GRPC_CLIENT_DIRECT_CHANNEL, &test_client_filter); - register_stage(GRPC_SERVER_CHANNEL, &test_server_filter); - }, - [&config] { test_request(config); }); -} - -void filter_status_code_pre_init(void) { - gpr_mu_init(&g_mu); - gpr_cv_init(&g_client_code_cv); - gpr_cv_init(&g_server_code_cv); -} diff --git a/test/core/end2end/tests/filtered_metadata.cc b/test/core/end2end/tests/filtered_metadata.cc index 025e5aa1953..4d91bca43c6 100644 --- a/test/core/end2end/tests/filtered_metadata.cc +++ b/test/core/end2end/tests/filtered_metadata.cc @@ -16,175 +16,64 @@ // // -#include +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Request/response with metadata which should be filtered -static void test_request_response_with_metadata_to_be_filtered( - const CoreTestConfiguration& config, const char* filtered_md_key, - const char* filter_md_value) { - grpc_call* c; - grpc_call* s; - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string(filtered_md_key), - grpc_slice_from_static_string(filter_md_value), - {{nullptr, nullptr, nullptr, nullptr}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string(filtered_md_key), - grpc_slice_from_static_string(filter_md_value), - {{nullptr, nullptr, nullptr, nullptr}}}}; - auto f = - begin_test(config, "test_request_response_with_metadata_to_be_filtered", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(!contains_metadata(&request_metadata_recv, filtered_md_key, - filter_md_value)); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key2", "val2")); - GPR_ASSERT(!contains_metadata(&initial_metadata_recv, filtered_md_key, - filter_md_value)); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +void TestRequestResponseWithMetadataToBeFiltered( + CoreEnd2endTest& test, absl::string_view filtered_md_key, + absl::string_view filter_md_value) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata( + {{"key1", "val1"}, {filtered_md_key, filter_md_value}}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + + auto s = test.RequestCall(101); + + test.Expect(101, true); + test.Step(); + + s.NewBatch(102).SendInitialMetadata( + {{"key2", "val2"}, {filtered_md_key, filter_md_value}}); + test.Expect(102, true); + test.Step(); + + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(s.GetInitialMetadata("key1"), "val1"); + EXPECT_EQ(s.GetInitialMetadata(filtered_md_key), absl::nullopt); + EXPECT_EQ(server_initial_metadata.Get("key2"), "val2"); + EXPECT_EQ(server_initial_metadata.Get(filtered_md_key), absl::nullopt); } -void filtered_metadata(const CoreTestConfiguration& config) { - test_request_response_with_metadata_to_be_filtered(config, "content-length", - "45"); +TEST_P(CoreEnd2endTest, ContentLengthIsFiltered) { + TestRequestResponseWithMetadataToBeFiltered(*this, "content-length", "45"); } -void filtered_metadata_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/graceful_server_shutdown.cc b/test/core/end2end/tests/graceful_server_shutdown.cc index 494dd3d0888..1f140664db6 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.cc +++ b/test/core/end2end/tests/graceful_server_shutdown.cc @@ -16,150 +16,45 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void test_early_server_shutdown_finishes_inflight_calls( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - auto f = - begin_test(config, "test_early_server_shutdown_finishes_inflight_calls", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); +namespace grpc_core { +namespace { + +TEST_P(Http2Test, GracefulServerShutdown) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); // shutdown and destroy the server - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv.VerifyEmpty(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - grpc_call_unref(s); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); -} - -void graceful_server_shutdown(const CoreTestConfiguration& config) { - test_early_server_shutdown_finishes_inflight_calls(config); + ShutdownServerAndNotify(200); + Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(200, true); + Expect(1, true); + Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -void graceful_server_shutdown_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/grpc_authz.cc b/test/core/end2end/tests/grpc_authz.cc index 667990b4a14..26d5da6cecd 100644 --- a/test/core/end2end/tests/grpc_authz.cc +++ b/test/core/end2end/tests/grpc_authz.cc @@ -12,502 +12,266 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - -#include -#include #include -#include #include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "gtest/gtest.h" #include #include -#include -#include #include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/notification.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/security/authorization/authorization_policy_provider.h" #include "src/core/lib/security/authorization/grpc_authorization_policy_provider.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" #include "test/core/util/tls_utils.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "%s", std::string(80, '*').c_str()); - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +namespace grpc_core { +namespace { + +void TestAllowAuthorizedRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); } -static void test_allow_authorized_request(CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - const char* error_string = nullptr; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - int was_cancelled = 2; - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->data.recv_status_on_client.error_string = &error_string; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - GPR_ASSERT(GRPC_STATUS_OK == status); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - gpr_free(const_cast(error_string)); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +void TestDenyUnauthorizedRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "Unauthorized RPC request rejected."); } -static void test_deny_unauthorized_request(CoreTestFixture* f) { - grpc_call* c; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - const char* error_string = nullptr; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->data.recv_status_on_client.error_string = &error_string; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(GRPC_STATUS_PERMISSION_DENIED == status); - GPR_ASSERT(0 == - grpc_slice_str_cmp(details, "Unauthorized RPC request rejected.")); - - grpc_slice_unref(details); - gpr_free(const_cast(error_string)); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); +void InitWithPolicy(CoreEnd2endTest& test, + grpc_authorization_policy_provider* provider) { + test.InitServer(ChannelArgs().Set( + GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER, + ChannelArgs::Pointer(provider, + grpc_authorization_policy_provider_arg_vtable()))); + test.InitClient(ChannelArgs()); } -static void test_static_init_allow_authorized_request( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; +void InitWithStaticData(CoreEnd2endTest& test, const char* authz_policy) { grpc_status_code code = GRPC_STATUS_OK; const char* error_details; grpc_authorization_policy_provider* provider = grpc_authorization_policy_provider_static_data_create(authz_policy, &code, &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_static_init_allow_authorized_request", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_allow_authorized_request(f.get()); + EXPECT_EQ(code, GRPC_STATUS_OK); + InitWithPolicy(test, provider); } -static void test_static_init_deny_unauthorized_request( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_bar\"," - " \"request\": {" - " \"paths\": [" - " \"*/bar\"" - " ]" - " }" - " }" - " ]," - " \"deny_rules\": [" - " {" - " \"name\": \"deny_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_static_data_create(authz_policy, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_static_init_deny_unauthorized_request", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_deny_unauthorized_request(f.get()); +class InitWithTempFile { + public: + InitWithTempFile(CoreEnd2endTest& test, const char* authz_policy) + : tmp_file_(authz_policy) { + grpc_status_code code = GRPC_STATUS_OK; + const char* error_details; + provider_ = grpc_authorization_policy_provider_file_watcher_create( + tmp_file_.name().c_str(), /*refresh_interval_sec=*/1, &code, + &error_details); + GPR_ASSERT(GRPC_STATUS_OK == code); + InitWithPolicy(test, provider_); + } + + InitWithTempFile(const InitWithTempFile&) = delete; + InitWithTempFile& operator=(const InitWithTempFile&) = delete; + + FileWatcherAuthorizationPolicyProvider* provider() { + return dynamic_cast(provider_); + } + + testing::TmpFile& file() { return tmp_file_; } + + private: + testing::TmpFile tmp_file_; + grpc_authorization_policy_provider* provider_; +}; + +TEST_P(SecureEnd2endTest, StaticInitAllowAuthorizedRequest) { + InitWithStaticData(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestAllowAuthorizedRequest(*this); } -static void test_static_init_deny_request_no_match_in_policy( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_bar\"," - " \"request\": {" - " \"paths\": [" - " \"*/bar\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_static_data_create(authz_policy, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = - begin_test(config, "test_static_init_deny_request_no_match_in_policy", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_deny_unauthorized_request(f.get()); +TEST_P(SecureEnd2endTest, StaticInitDenyUnauthorizedRequest) { + InitWithStaticData(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_bar\"," + " \"request\": {" + " \"paths\": [" + " \"*/bar\"" + " ]" + " }" + " }" + " ]," + " \"deny_rules\": [" + " {" + " \"name\": \"deny_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestDenyUnauthorizedRequest(*this); } -static void test_file_watcher_init_allow_authorized_request( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_file_watcher_init_allow_authorized_request", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_allow_authorized_request(f.get()); +TEST_P(SecureEnd2endTest, StaticInitDenyRequestNoMatchInPolicy) { + InitWithStaticData(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_bar\"," + " \"request\": {" + " \"paths\": [" + " \"*/bar\"" + " ]" + " }" + " }" + " ]" + "}"); + TestDenyUnauthorizedRequest(*this); } -static void test_file_watcher_init_deny_unauthorized_request( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_bar\"," - " \"request\": {" - " \"paths\": [" - " \"*/bar\"" - " ]" - " }" - " }" - " ]," - " \"deny_rules\": [" - " {" - " \"name\": \"deny_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = - begin_test(config, "test_file_watcher_init_deny_unauthorized_request", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_deny_unauthorized_request(f.get()); +TEST_P(SecureEnd2endTest, FileWatcherInitAllowAuthorizedRequest) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestAllowAuthorizedRequest(*this); } -static void test_file_watcher_init_deny_request_no_match_in_policy( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_bar\"," - " \"request\": {" - " \"paths\": [" - " \"*/bar\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, - "test_file_watcher_init_deny_request_no_match_in_policy", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_deny_unauthorized_request(f.get()); +TEST_P(SecureEnd2endTest, FileWatcherInitDenyUnauthorizedRequest) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_bar\"," + " \"request\": {" + " \"paths\": [" + " \"*/bar\"" + " ]" + " }" + " }" + " ]," + " \"deny_rules\": [" + " {" + " \"name\": \"deny_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestDenyUnauthorizedRequest(*this); } -static void test_file_watcher_valid_policy_reload( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; +TEST_P(SecureEnd2endTest, FileWatcherInitDenyRequestNoMatchInPolicy) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_bar\"," + " \"request\": {" + " \"paths\": [" + " \"*/bar\"" + " ]" + " }" + " }" + " ]" + "}"); + TestDenyUnauthorizedRequest(*this); +} - auto f = begin_test(config, "test_file_watcher_valid_policy_reload", nullptr, - &server_args); - grpc_authorization_policy_provider_release(provider); - test_allow_authorized_request(f.get()); - gpr_event on_reload_done; - gpr_event_init(&on_reload_done); - std::function callback = +TEST_P(SecureEnd2endTest, FileWatcherValidPolicyReload) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestAllowAuthorizedRequest(*this); + Notification on_reload_done; + tmp_policy.provider()->SetCallbackForTesting( [&on_reload_done](bool contents_changed, absl::Status status) { if (contents_changed) { - GPR_ASSERT(status.ok()); - gpr_event_set(&on_reload_done, reinterpret_cast(1)); + EXPECT_EQ(status, absl::OkStatus()); + on_reload_done.Notify(); } - }; - dynamic_cast(provider) - ->SetCallbackForTesting(std::move(callback)); + }); // Replace existing policy in file with a different authorization policy. - authz_policy = + tmp_policy.file().RewriteFile( "{" " \"name\": \"authz\"," " \"allow_rules\": [" @@ -530,142 +294,84 @@ static void test_file_watcher_valid_policy_reload( " }" " }" " ]" - "}"; - tmp_policy.RewriteFile(authz_policy); - GPR_ASSERT( - reinterpret_cast(1) == - gpr_event_wait(&on_reload_done, gpr_inf_future(GPR_CLOCK_MONOTONIC))); - test_deny_unauthorized_request(f.get()); - dynamic_cast(provider) - ->SetCallbackForTesting(nullptr); + "}"); + on_reload_done.WaitForNotification(); + TestDenyUnauthorizedRequest(*this); + tmp_policy.provider()->SetCallbackForTesting(nullptr); } -static void test_file_watcher_invalid_policy_skip_reload( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_file_watcher_invalid_policy_skip_reload", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_allow_authorized_request(f.get()); - gpr_event on_reload_done; - gpr_event_init(&on_reload_done); - std::function callback = +TEST_P(SecureEnd2endTest, FileWatcherInvalidPolicySkipReload) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestAllowAuthorizedRequest(*this); + Notification on_reload_done; + tmp_policy.provider()->SetCallbackForTesting( [&on_reload_done](bool contents_changed, absl::Status status) { if (contents_changed) { - GPR_ASSERT(absl::StatusCode::kInvalidArgument == status.code()); - GPR_ASSERT("\"name\" field is not present." == status.message()); - gpr_event_set(&on_reload_done, reinterpret_cast(1)); + EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(status.message(), "\"name\" field is not present."); + on_reload_done.Notify(); } - }; - dynamic_cast(provider) - ->SetCallbackForTesting(std::move(callback)); + }); // Replace exisiting policy in file with an invalid policy. - authz_policy = "{}"; - tmp_policy.RewriteFile(authz_policy); - GPR_ASSERT( - reinterpret_cast(1) == - gpr_event_wait(&on_reload_done, gpr_inf_future(GPR_CLOCK_MONOTONIC))); - test_allow_authorized_request(f.get()); - dynamic_cast(provider) - ->SetCallbackForTesting(nullptr); + tmp_policy.file().RewriteFile("{}"); + on_reload_done.WaitForNotification(); + TestAllowAuthorizedRequest(*this); + tmp_policy.provider()->SetCallbackForTesting(nullptr); } -static void test_file_watcher_recovers_from_failure( - const CoreTestConfiguration& config) { - const char* authz_policy = - "{" - " \"name\": \"authz\"," - " \"allow_rules\": [" - " {" - " \"name\": \"allow_foo\"," - " \"request\": {" - " \"paths\": [" - " \"*/foo\"" - " ]" - " }" - " }" - " ]" - "}"; - grpc_core::testing::TmpFile tmp_policy(authz_policy); - grpc_status_code code = GRPC_STATUS_OK; - const char* error_details; - grpc_authorization_policy_provider* provider = - grpc_authorization_policy_provider_file_watcher_create( - tmp_policy.name().c_str(), /*refresh_interval_sec=*/1, &code, - &error_details); - GPR_ASSERT(GRPC_STATUS_OK == code); - grpc_arg args[] = { - grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER), provider, - grpc_authorization_policy_provider_arg_vtable()), - }; - grpc_channel_args server_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_file_watcher_recovers_from_failure", - nullptr, &server_args); - grpc_authorization_policy_provider_release(provider); - test_allow_authorized_request(f.get()); - gpr_event on_first_reload_done; - gpr_event_init(&on_first_reload_done); - std::function callback1 = +TEST_P(SecureEnd2endTest, FileWatcherRecoversFromFailure) { + InitWithTempFile tmp_policy(*this, + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_foo\"," + " \"request\": {" + " \"paths\": [" + " \"*/foo\"" + " ]" + " }" + " }" + " ]" + "}"); + TestAllowAuthorizedRequest(*this); + Notification on_first_reload_done; + tmp_policy.provider()->SetCallbackForTesting( [&on_first_reload_done](bool contents_changed, absl::Status status) { if (contents_changed) { - GPR_ASSERT(absl::StatusCode::kInvalidArgument == status.code()); - GPR_ASSERT("\"name\" field is not present." == status.message()); - gpr_event_set(&on_first_reload_done, reinterpret_cast(1)); + EXPECT_EQ(status.code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(status.message(), "\"name\" field is not present."); + on_first_reload_done.Notify(); } - }; - dynamic_cast(provider) - ->SetCallbackForTesting(std::move(callback1)); + }); // Replace exisiting policy in file with an invalid policy. - authz_policy = "{}"; - tmp_policy.RewriteFile(authz_policy); - GPR_ASSERT(reinterpret_cast(1) == - gpr_event_wait(&on_first_reload_done, - gpr_inf_future(GPR_CLOCK_MONOTONIC))); - test_allow_authorized_request(f.get()); - gpr_event on_second_reload_done; - gpr_event_init(&on_second_reload_done); - std::function callback2 = + tmp_policy.file().RewriteFile("{}"); + on_first_reload_done.WaitForNotification(); + TestAllowAuthorizedRequest(*this); + Notification on_second_reload_done; + tmp_policy.provider()->SetCallbackForTesting( [&on_second_reload_done](bool contents_changed, absl::Status status) { if (contents_changed) { - GPR_ASSERT(status.ok()); - gpr_event_set(&on_second_reload_done, reinterpret_cast(1)); + EXPECT_EQ(status, absl::OkStatus()); + on_second_reload_done.Notify(); } - }; - dynamic_cast(provider) - ->SetCallbackForTesting(std::move(callback2)); + }); // Recover from reload errors, by replacing invalid policy in file with a // valid policy. - authz_policy = + tmp_policy.file().RewriteFile( "{" " \"name\": \"authz\"," " \"allow_rules\": [" @@ -688,26 +394,11 @@ static void test_file_watcher_recovers_from_failure( " }" " }" " ]" - "}"; - tmp_policy.RewriteFile(authz_policy); - GPR_ASSERT(reinterpret_cast(1) == - gpr_event_wait(&on_second_reload_done, - gpr_inf_future(GPR_CLOCK_MONOTONIC))); - test_deny_unauthorized_request(f.get()); - dynamic_cast(provider) - ->SetCallbackForTesting(nullptr); -} - -void grpc_authz(const CoreTestConfiguration& config) { - test_static_init_allow_authorized_request(config); - test_static_init_deny_unauthorized_request(config); - test_static_init_deny_request_no_match_in_policy(config); - test_file_watcher_init_allow_authorized_request(config); - test_file_watcher_init_deny_unauthorized_request(config); - test_file_watcher_init_deny_request_no_match_in_policy(config); - test_file_watcher_valid_policy_reload(config); - test_file_watcher_invalid_policy_skip_reload(config); - test_file_watcher_recovers_from_failure(config); + "}"); + on_second_reload_done.WaitForNotification(); + TestDenyUnauthorizedRequest(*this); + tmp_policy.provider()->SetCallbackForTesting(nullptr); } -void grpc_authz_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/high_initial_seqno.cc b/test/core/end2end/tests/high_initial_seqno.cc index 88eb8db09fe..f73efb3c8ed 100644 --- a/test/core/end2end/tests/high_initial_seqno.cc +++ b/test/core/end2end/tests/high_initial_seqno.cc @@ -16,175 +16,60 @@ // // -#include - -#include -#include -#include - -#include "absl/strings/str_cat.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +namespace grpc_core { +namespace { + +void SimpleRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); // TODO(ctiller): this rate limits the test, and it should be removed when // retry has been implemented; until then cross-thread chatter // may result in some requests needing to be cancelled due to // seqno exhaustion. - cqv.VerifyEmpty(); + test.Step(); } -static void test_invoke_10_simple_requests(const CoreTestConfiguration& config, - int initial_sequence_number) { - int i; - - grpc_arg client_arg; - grpc_channel_args client_args; - - client_arg.type = GRPC_ARG_INTEGER; - client_arg.key = const_cast(GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER); - client_arg.value.integer = initial_sequence_number; - - client_args.num_args = 1; - client_args.args = &client_arg; - - std::string name = absl::StrCat("test_invoke_requests first_seqno=", - initial_sequence_number); - auto f = begin_test(config, name.c_str(), &client_args, nullptr); - for (i = 0; i < 10; i++) { - simple_request_body(config, f.get()); - gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); +void TenRequests(CoreEnd2endTest& test, int initial_sequence_number) { + test.InitServer(ChannelArgs()); + test.InitClient(ChannelArgs().Set(GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, + initial_sequence_number)); + for (int i = 0; i < 10; i++) { + SimpleRequest(test); } } -void high_initial_seqno(const CoreTestConfiguration& config) { - test_invoke_10_simple_requests(config, 16777213); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) { - test_invoke_10_simple_requests(config, 2147483645); - } -} +TEST_P(Http2Test, HighInitialSeqno) { TenRequests(*this, 16777213); } +TEST_P(RetryHttp2Test, HighInitialSeqno) { TenRequests(*this, 2147483645); } -void high_initial_seqno_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/hpack_size.cc b/test/core/end2end/tests/hpack_size.cc index 11cb650f291..b55d9930631 100644 --- a/test/core/end2end/tests/hpack_size.cc +++ b/test/core/end2end/tests/hpack_size.cc @@ -17,337 +17,207 @@ // #include -#include -#include -#include -#include -#include +#include +#include -#include "absl/strings/str_format.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/time.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/no_destruct.h" #include "test/core/end2end/end2end_tests.h" -const char* hobbits[][2] = { - {"Adaldrida", "Brandybuck"}, {"Adamanta", "Took"}, - {"Adalgrim", "Took"}, {"Adelard", "Took"}, - {"Amaranth", "Brandybuck"}, {"Andwise", "Roper"}, - {"Angelica", "Baggins"}, {"Asphodel", "Burrows"}, - {"Balbo", "Baggins"}, {"Bandobras", "Took"}, - {"Belba", "Bolger"}, {"Bell", "Gamgee"}, - {"Belladonna", "Baggins"}, {"Berylla", "Baggins"}, - {"Bilbo", "Baggins"}, {"Bilbo", "Gardner"}, - {"Bill", "Butcher"}, {"Bingo", "Baggins"}, - {"Bodo", "Proudfoot"}, {"Bowman", "Cotton"}, - {"Bungo", "Baggins"}, {"Camellia", "Sackville"}, - {"Carl", "Cotton"}, {"Celandine", "Brandybuck"}, - {"Chica", "Baggins"}, {"Daddy", "Twofoot"}, - {"Daisy", "Boffin"}, {"Diamond", "Took"}, - {"Dinodas", "Brandybuck"}, {"Doderic", "Brandybuck"}, - {"Dodinas", "Brandybuck"}, {"Donnamira", "Boffin"}, - {"Dora", "Baggins"}, {"Drogo", "Baggins"}, - {"Dudo", "Baggins"}, {"Eglantine", "Took"}, - {"Elanor", "Fairbairn"}, {"Elfstan", "Fairbairn"}, - {"Esmeralda", "Brandybuck"}, {"Estella", "Brandybuck"}, - {"Everard", "Took"}, {"Falco", "Chubb-Baggins"}, - {"Faramir", "Took"}, {"Farmer", "Maggot"}, - {"Fastolph", "Bolger"}, {"Ferdibrand", "Took"}, - {"Ferdinand", "Took"}, {"Ferumbras", "Took"}, - {"Ferumbras", "Took"}, {"Filibert", "Bolger"}, - {"Firiel", "Fairbairn"}, {"Flambard", "Took"}, - {"Folco", "Boffin"}, {"Fortinbras", "Took"}, - {"Fortinbras", "Took"}, {"Fosco", "Baggins"}, - {"Fredegar", "Bolger"}, {"Frodo", "Baggins"}, - {"Frodo", "Gardner"}, {"Gerontius", "Took"}, - {"Gilly", "Baggins"}, {"Goldilocks", "Took"}, - {"Gorbadoc", "Brandybuck"}, {"Gorbulas", "Brandybuck"}, - {"Gorhendad", "Brandybuck"}, {"Gormadoc", "Brandybuck"}, - {"Griffo", "Boffin"}, {"Halfast", "Gamgee"}, - {"Halfred", "Gamgee"}, {"Halfred", "Greenhand"}, - {"Hanna", "Brandybuck"}, {"Hamfast", "Gamgee"}, - {"Hamfast", "Gardner"}, {"Hamson", "Gamgee"}, - {"Harding", "Gardner"}, {"Hilda", "Brandybuck"}, - {"Hildibrand", "Took"}, {"Hildifons", "Took"}, - {"Hildigard", "Took"}, {"Hildigrim", "Took"}, - {"Hob", "Gammidge"}, {"Hob", "Hayward"}, - {"Hobson", "Gamgee"}, {"Holfast", "Gardner"}, - {"Holman", "Cotton"}, {"Holman", "Greenhand"}, - {"Hugo", "Boffin"}, {"Hugo", "Bracegirdle"}, - {"Ilberic", "Brandybuck"}, {"Isembard", "Took"}, - {"Isembold", "Took"}, {"Isengar", "Took"}, - {"Isengrim", "Took"}, {"Isengrim", "Took"}, - {"Isumbras", "Took"}, {"Isumbras", "Took"}, - {"Jolly", "Cotton"}, - // - //{"Lalia", "Took"}, - //{"Largo", "Baggins"}, - //{"Laura", "Baggins"}, - //{"Lily", "Goodbody"}, - //{"Lily", "Cotton"}, - //{"Linda", "Proudfoot"}, - //{"Lobelia", "Sackville-Baggins"}, - //{"Longo", "Baggins"}, - //{"Lotho", "Sackville-Baggins"}, - //{"Madoc", "Brandybuck"}, - //{"Malva", "Brandybuck"}, - //{"Marigold", "Cotton"}, - //{"Marmadas", "Brandybuck"}, - //{"Marmadoc", "Brandybuck"}, - //{"Marroc", "Brandybuck"}, - //{"May", "Gamgee"}, - //{"Melilot", "Brandybuck"}, - //{"Menegilda", "Brandybuck"}, - //{"Mentha", "Brandybuck"}, - //{"Meriadoc", "Brandybuck"}, - //{"Merimac", "Brandybuck"}, - //{"Merimas", "Brandybuck"}, - //{"Merry", "Gardner"}, - //{"Milo", "Burrows"}, - //{"Mimosa", "Baggins"}, - //{"Minto", "Burrows"}, - //{"Mirabella", "Brandybuck"}, - //{"Moro", "Burrows"}, - //{"Mosco", "Burrows"}, - //{"Mungo", "Baggins"}, - //{"Myrtle", "Burrows"}, - //{"Odo", "Proudfoot"}, - //{"Odovacar", "Bolger"}, - //{"Olo", "Proudfoot"}, - //{"Orgulas", "Brandybuck"}, - //{"Otho", "Sackville-Baggins"}, - //{"Paladin", "Took"}, - //{"Pansy", "Bolger"}, - //{"Pearl", "Took"}, - //{"Peony", "Burrows"}, - //{"Peregrin", "Took"}, - //{"Pervinca", "Took"}, - //{"Pimpernel", "Took"}, - //{"Pippin", "Gardner"}, - //{"Polo", "Baggins"}, - //{"Ponto", "Baggins"}, - //{"Porto", "Baggins"}, - //{"Posco", "Baggins"}, - //{"Poppy", "Bolger"}, - //{"Primrose", "Gardner"}, - //{"Primula", "Baggins"}, - //{"Prisca", "Bolger"}, - //{"Reginard", "Took"}, - //{"Robin", "Smallburrow"}, - //{"Robin", "Gardner"}, - //{"Rorimac", "Brandybuck"}, - //{"Rosa", "Took"}, - //{"Rosamunda", "Bolger"}, - //{"Rose", "Gardner"}, - //{"Ruby", "Baggins"}, - //{"Ruby", "Gardner"}, - //{"Rudigar", "Bolger"}, - //{"Rufus", "Burrows"}, - //{"Sadoc", "Brandybuck"}, - //{"Salvia", "Bolger"}, - //{"Samwise", "Gamgee"}, - //{"Sancho", "Proudfoot"}, - //{"Saradas", "Brandybuck"}, - //{"Saradoc", "Brandybuck"}, - //{"Seredic", "Brandybuck"}, - //{"Sigismond", "Took"}, - //{"Smeagol", "Gollum"}, - //{"Tanta", "Baggins"}, - //{"Ted", "Sandyman"}, - //{"Tobold", "Hornblower"}, - //{"Togo", "Goodbody"}, - //{"Tolman", "Cotton"}, - //{"Tolman", "Gardner"}, - //{"Widow", "Rumble"}, - //{"Wilcome", "Cotton"}, - //{"Wilcome", "Cotton"}, - //{"Wilibald", "Bolger"}, - //{"Will", "Whitfoot"}, - //{"Wiseman", "Gamwich"} -}; - -const char* dragons[] = {"Ancalagon", "Glaurung", "Scatha", - "Smaug the Magnificent"}; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +namespace grpc_core { +namespace { +const NoDestruct>> + hobbits(std::vector>{ + {"Adaldrida", "Brandybuck"}, {"Adamanta", "Took"}, + {"Adalgrim", "Took"}, {"Adelard", "Took"}, + {"Amaranth", "Brandybuck"}, {"Andwise", "Roper"}, + {"Angelica", "Baggins"}, {"Asphodel", "Burrows"}, + {"Balbo", "Baggins"}, {"Bandobras", "Took"}, + {"Belba", "Bolger"}, {"Bell", "Gamgee"}, + {"Belladonna", "Baggins"}, {"Berylla", "Baggins"}, + {"Bilbo", "Baggins"}, {"Bilbo", "Gardner"}, + {"Bill", "Butcher"}, {"Bingo", "Baggins"}, + {"Bodo", "Proudfoot"}, {"Bowman", "Cotton"}, + {"Bungo", "Baggins"}, {"Camellia", "Sackville"}, + {"Carl", "Cotton"}, {"Celandine", "Brandybuck"}, + {"Chica", "Baggins"}, {"Daddy", "Twofoot"}, + {"Daisy", "Boffin"}, {"Diamond", "Took"}, + {"Dinodas", "Brandybuck"}, {"Doderic", "Brandybuck"}, + {"Dodinas", "Brandybuck"}, {"Donnamira", "Boffin"}, + {"Dora", "Baggins"}, {"Drogo", "Baggins"}, + {"Dudo", "Baggins"}, {"Eglantine", "Took"}, + {"Elanor", "Fairbairn"}, {"Elfstan", "Fairbairn"}, + {"Esmeralda", "Brandybuck"}, {"Estella", "Brandybuck"}, + {"Everard", "Took"}, {"Falco", "Chubb-Baggins"}, + {"Faramir", "Took"}, {"Farmer", "Maggot"}, + {"Fastolph", "Bolger"}, {"Ferdibrand", "Took"}, + {"Ferdinand", "Took"}, {"Ferumbras", "Took"}, + {"Ferumbras", "Took"}, {"Filibert", "Bolger"}, + {"Firiel", "Fairbairn"}, {"Flambard", "Took"}, + {"Folco", "Boffin"}, {"Fortinbras", "Took"}, + {"Fortinbras", "Took"}, {"Fosco", "Baggins"}, + {"Fredegar", "Bolger"}, {"Frodo", "Baggins"}, + {"Frodo", "Gardner"}, {"Gerontius", "Took"}, + {"Gilly", "Baggins"}, {"Goldilocks", "Took"}, + {"Gorbadoc", "Brandybuck"}, {"Gorbulas", "Brandybuck"}, + {"Gorhendad", "Brandybuck"}, {"Gormadoc", "Brandybuck"}, + {"Griffo", "Boffin"}, {"Halfast", "Gamgee"}, + {"Halfred", "Gamgee"}, {"Halfred", "Greenhand"}, + {"Hanna", "Brandybuck"}, {"Hamfast", "Gamgee"}, + {"Hamfast", "Gardner"}, {"Hamson", "Gamgee"}, + {"Harding", "Gardner"}, {"Hilda", "Brandybuck"}, + {"Hildibrand", "Took"}, {"Hildifons", "Took"}, + {"Hildigard", "Took"}, {"Hildigrim", "Took"}, + {"Hob", "Gammidge"}, {"Hob", "Hayward"}, + {"Hobson", "Gamgee"}, {"Holfast", "Gardner"}, + {"Holman", "Cotton"}, {"Holman", "Greenhand"}, + {"Hugo", "Boffin"}, {"Hugo", "Bracegirdle"}, + {"Ilberic", "Brandybuck"}, {"Isembard", "Took"}, + {"Isembold", "Took"}, {"Isengar", "Took"}, + {"Isengrim", "Took"}, {"Isengrim", "Took"}, + {"Isumbras", "Took"}, {"Isumbras", "Took"}, + {"Jolly", "Cotton"}, + }); + +const NoDestruct> dragons( + std::vector{"Ancalagon", "Glaurung", "Scatha", + "Smaug the Magnificent"}); + +void SimpleRequestBody(CoreEnd2endTest& test, size_t index) { + const auto& hobbit = (*hobbits)[index % hobbits->size()]; + const auto& dragon = (*dragons)[index % dragons->size()]; + auto method = + absl::StrCat("/", hobbit.first, ".", hobbit.second, "/", dragon); + auto c = test.NewClientCall(method).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({ + {"hobbit-first-name", (*hobbits)[index % hobbits->size()].first}, + {"hobbit-second-name", (*hobbits)[index % hobbits->size()].second}, + {"dragon", (*dragons)[index % dragons->size()]}, + }) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, dragon, {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), dragon); + EXPECT_EQ(s.method(), method); + EXPECT_FALSE(client_close.was_cancelled()); } -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f, size_t index) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_metadata extra_metadata[3]; - grpc_slice details; - int was_cancelled = 2; - - memset(extra_metadata, 0, sizeof(extra_metadata)); - extra_metadata[0].key = grpc_slice_from_static_string("hobbit-first-name"); - extra_metadata[0].value = grpc_slice_from_static_string( - hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]); - extra_metadata[1].key = grpc_slice_from_static_string("hobbit-second-name"); - extra_metadata[1].value = grpc_slice_from_static_string( - hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]); - extra_metadata[2].key = grpc_slice_from_static_string("dragon"); - extra_metadata[2].value = - grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]); - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, gpr_inf_future(GPR_CLOCK_MONOTONIC), - nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = GPR_ARRAY_SIZE(extra_metadata); - op->data.send_initial_metadata.metadata = extra_metadata; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(grpc_core::Duration::Seconds(120)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(grpc_core::Duration::Seconds(120)); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -static void test_size(const CoreTestConfiguration& config, int encode_size, - int decode_size) { - size_t i; - - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_arg client_arg; - grpc_channel_args client_args; - - server_arg.type = GRPC_ARG_INTEGER; - server_arg.key = const_cast(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER); - server_arg.value.integer = decode_size; - server_args.num_args = 1; - server_args.args = &server_arg; - - client_arg.type = GRPC_ARG_INTEGER; - client_arg.key = const_cast(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER); - client_arg.value.integer = encode_size; - client_args.num_args = 1; - client_args.args = &client_arg; - - std::string name = - absl::StrFormat("test_size:e=%d:d=%d", encode_size, decode_size); - auto f = begin_test(config, name.c_str(), - encode_size != 4096 ? &client_args : nullptr, - decode_size != 4096 ? &server_args : nullptr); - for (i = 0; i < 4 * GPR_ARRAY_SIZE(hobbits); i++) { - simple_request_body(config, f.get(), i); +void HpackSize(CoreEnd2endTest& test, int encode_size, int decode_size) { + // TODO(ctiller): right now the hpack encoder isn't compressing these, so this + // test doesn't do what we want - which is to test overflow the hpack table + // slot count. + test.InitServer( + ChannelArgs().Set(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER, decode_size)); + test.InitClient( + ChannelArgs().Set(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER, encode_size)); + for (size_t i = 0; i < 4 * hobbits->size(); i++) { + SimpleRequestBody(test, i); } } -void hpack_size(const CoreTestConfiguration& config) { - static const int interesting_sizes[] = {4096, 0, 100, - 1000, 32768, 4 * 1024 * 1024}; - size_t i, j; - - for (i = 0; i < GPR_ARRAY_SIZE(interesting_sizes); i++) { - for (j = 0; j < GPR_ARRAY_SIZE(interesting_sizes); j++) { - test_size(config, interesting_sizes[i], interesting_sizes[j]); - } - } +TEST_P(Http2SingleHopTest, Encode0Decode0) { HpackSize(*this, 0, 0); } +TEST_P(Http2SingleHopTest, Encode0Decode100) { HpackSize(*this, 0, 100); } +TEST_P(Http2SingleHopTest, Encode0Decode1000) { HpackSize(*this, 0, 1000); } +TEST_P(Http2SingleHopTest, Encode0Decode4096) { HpackSize(*this, 0, 4096); } +TEST_P(Http2SingleHopTest, Encode0Decode32768) { HpackSize(*this, 0, 32768); } +TEST_P(Http2SingleHopTest, Encode0Decode4194304) { + HpackSize(*this, 0, 4194304); +} +TEST_P(Http2SingleHopTest, Encode100Decode0) { HpackSize(*this, 100, 0); } +TEST_P(Http2SingleHopTest, Encode100Decode100) { HpackSize(*this, 100, 100); } +TEST_P(Http2SingleHopTest, Encode100Decode1000) { HpackSize(*this, 100, 1000); } +TEST_P(Http2SingleHopTest, Encode100Decode4096) { HpackSize(*this, 100, 4096); } +TEST_P(Http2SingleHopTest, Encode100Decode32768) { + HpackSize(*this, 100, 32768); +} +TEST_P(Http2SingleHopTest, Encode100Decode4194304) { + HpackSize(*this, 100, 4194304); +} +TEST_P(Http2SingleHopTest, Encode1000Decode0) { HpackSize(*this, 1000, 0); } +TEST_P(Http2SingleHopTest, Encode1000Decode100) { HpackSize(*this, 1000, 100); } +TEST_P(Http2SingleHopTest, Encode1000Decode1000) { + HpackSize(*this, 1000, 1000); +} +TEST_P(Http2SingleHopTest, Encode1000Decode4096) { + HpackSize(*this, 1000, 4096); +} +TEST_P(Http2SingleHopTest, Encode1000Decode32768) { + HpackSize(*this, 1000, 32768); +} +TEST_P(Http2SingleHopTest, Encode1000Decode4194304) { + HpackSize(*this, 1000, 4194304); +} +TEST_P(Http2SingleHopTest, Encode4096Decode0) { HpackSize(*this, 4096, 0); } +TEST_P(Http2SingleHopTest, Encode4096Decode100) { HpackSize(*this, 4096, 100); } +TEST_P(Http2SingleHopTest, Encode4096Decode1000) { + HpackSize(*this, 4096, 1000); +} +TEST_P(Http2SingleHopTest, Encode4096Decode4096) { + HpackSize(*this, 4096, 4096); +} +TEST_P(Http2SingleHopTest, Encode4096Decode32768) { + HpackSize(*this, 4096, 32768); +} +TEST_P(Http2SingleHopTest, Encode4096Decode4194304) { + HpackSize(*this, 4096, 4194304); +} +TEST_P(Http2SingleHopTest, Encode32768Decode0) { HpackSize(*this, 32768, 0); } +TEST_P(Http2SingleHopTest, Encode32768Decode100) { + HpackSize(*this, 32768, 100); +} +TEST_P(Http2SingleHopTest, Encode32768Decode1000) { + HpackSize(*this, 32768, 1000); +} +TEST_P(Http2SingleHopTest, Encode32768Decode4096) { + HpackSize(*this, 32768, 4096); +} +TEST_P(Http2SingleHopTest, Encode32768Decode32768) { + HpackSize(*this, 32768, 32768); +} +TEST_P(Http2SingleHopTest, Encode32768Decode4194304) { + HpackSize(*this, 32768, 4194304); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode0) { + HpackSize(*this, 4194304, 0); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode100) { + HpackSize(*this, 4194304, 100); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode1000) { + HpackSize(*this, 4194304, 1000); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode4096) { + HpackSize(*this, 4194304, 4096); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode32768) { + HpackSize(*this, 4194304, 32768); +} +TEST_P(Http2SingleHopTest, Encode4194304Decode4194304) { + HpackSize(*this, 4194304, 4194304); } -void hpack_size_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/invoke_large_request.cc b/test/core/end2end/tests/invoke_large_request.cc index 8b91583c697..de6f6ffb3f2 100644 --- a/test/core/end2end/tests/invoke_large_request.cc +++ b/test/core/end2end/tests/invoke_large_request.cc @@ -18,218 +18,60 @@ #include -#include -#include -#include -#include +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/debug/event_log.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/no_destruct.h" #include "src/core/lib/gprpp/time.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/slice/slice.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +namespace grpc_core { +namespace { + +TEST_P(Http2SingleHopTest, InvokeLargeRequest) { + const size_t kMessageSize = 10 * 1024 * 1024; + InitServer( + ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, kMessageSize)); + InitClient( + ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, kMessageSize)); + auto c = NewClientCall("/foo").Timeout(Duration::Minutes(5)).Create(); + auto send_from_client = RandomSlice(kMessageSize); + auto send_from_server = RandomSlice(kMessageSize); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage(send_from_client.Ref()) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(Duration::Minutes(1)); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + Expect(102, true); + Step(Duration::Minutes(1)); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .SendMessage(send_from_server.Ref()) + .RecvCloseOnServer(client_close); + Expect(103, true); + Expect(1, true); + Step(Duration::Minutes(1)); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), send_from_client); + EXPECT_EQ(server_message.payload(), send_from_server); } -static grpc_slice make_slice(int message_size) { - GPR_ASSERT(message_size > 0); - grpc_slice slice = grpc_slice_malloc(message_size); - memset(GRPC_SLICE_START_PTR(slice), 'x', GRPC_SLICE_LENGTH(slice)); - return slice; -} - -static void test_invoke_large_request(const CoreTestConfiguration& config, - int message_size) { - grpc_arg args[1]; - args[0].type = GRPC_ARG_INTEGER; - args[0].key = const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); - args[0].value.integer = message_size; - grpc_channel_args channel_args = {GPR_ARRAY_SIZE(args), args}; - - auto f = begin_test(config, "test_invoke_large_request", &channel_args, - &channel_args); - - grpc_slice request_payload_slice = make_slice(message_size); - grpc_slice response_payload_slice = make_slice(message_size); - grpc_call* c; - grpc_call* s; - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(300); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(grpc_core::Duration::Seconds(60)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(grpc_core::Duration::Seconds(60)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(grpc_core::Duration::Seconds(60)); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); -} - -static grpc_core::NoDestruct g_event_log; - -void invoke_large_request(const CoreTestConfiguration& config) { - { - grpc_core::ExecCtx exec_ctx; - g_event_log->BeginCollection(); - } - test_invoke_large_request(config, 10 * 1024 * 1024); - std::vector events; - grpc_core::ExecCtx exec_ctx; - gpr_log(GPR_ERROR, "event_log:\n%s", - g_event_log - ->EndCollectionAndReportCsv({"logging", "tcp-write-outstanding"}) - .c_str()); -} - -void invoke_large_request_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc index 278fbd86409..164de997702 100644 --- a/test/core/end2end/tests/keepalive_timeout.cc +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -16,320 +16,96 @@ // // -#include - -#include -#include - #include "absl/strings/string_view.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include "src/core/ext/transport/chttp2/transport/frame_ping.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/config_vars.h" -#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/port.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "%s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Client sends a request, then waits for the keepalive watchdog timeouts before // returning status. -static void test_keepalive_timeout(const CoreTestConfiguration& config) { - grpc_call* c; - - grpc_arg keepalive_arg_elems[3]; - keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); - keepalive_arg_elems[0].value.integer = 10; - keepalive_arg_elems[1].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[1].key = const_cast(GRPC_ARG_KEEPALIVE_TIMEOUT_MS); - keepalive_arg_elems[1].value.integer = 0; - keepalive_arg_elems[2].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - keepalive_arg_elems[2].value.integer = 0; - grpc_channel_args keepalive_args = {GPR_ARRAY_SIZE(keepalive_arg_elems), - keepalive_arg_elems}; - - auto f = begin_test(config, "keepalive_timeout", &keepalive_args, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - +TEST_P(Http2SingleHopTest, KeepaliveTimeout) { // Disable ping ack to trigger the keepalive timeout - grpc_set_disable_ping_ack(true); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); + InitServer(ChannelArgs().Set("grpc.http2.ack_pings", false)); + InitClient(ChannelArgs() + .Set(GRPC_ARG_KEEPALIVE_TIME_MS, 10) + .Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 0) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, false)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + EXPECT_EQ(server_status.message(), "keepalive watchdog timeout"); } // Verify that reads reset the keepalive ping timer. The client sends 30 pings // with a sleep of 10ms in between. It has a configured keepalive timer of // 200ms. In the success case, each ping ack should reset the keepalive timer so // that the keepalive ping is never sent. -static void test_read_delays_keepalive(const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, ReadDelaysKeepalive) { #ifdef GRPC_POSIX_SOCKET - /* It is hard to get the timing right for the polling engine poll. */ - if (grpc_core::ConfigVars::Get().PollStrategy() == "poll") return; + // It is hard to get the timing right for the polling engine poll. + if (ConfigVars::Get().PollStrategy() == "poll") { + GTEST_SKIP() << "Skipping test under poll poller"; + } #endif // GRPC_POSIX_SOCKET - const int kPingIntervalMS = 100; - grpc_arg keepalive_arg_elems[3]; - keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); - keepalive_arg_elems[0].value.integer = 20 * kPingIntervalMS; - keepalive_arg_elems[1].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[1].key = const_cast(GRPC_ARG_KEEPALIVE_TIMEOUT_MS); - keepalive_arg_elems[1].value.integer = 0; - keepalive_arg_elems[2].type = GRPC_ARG_INTEGER; - keepalive_arg_elems[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - keepalive_arg_elems[2].value.integer = 0; - grpc_channel_args keepalive_args = {GPR_ARRAY_SIZE(keepalive_arg_elems), - keepalive_arg_elems}; - auto f = begin_test(config, "test_read_delays_keepalive", &keepalive_args, - nullptr); + const auto kPingInterval = Duration::Milliseconds(100); // Disable ping ack to trigger the keepalive timeout - grpc_set_disable_ping_ack(true); - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_byte_buffer* request_payload; - grpc_byte_buffer* request_payload_recv; - grpc_byte_buffer* response_payload; - grpc_byte_buffer* response_payload_recv; - int i; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(100), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(101), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (i = 0; i < 30; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); + InitServer(ChannelArgs().Set("grpc.http2.ack_pings", false)); + InitClient(ChannelArgs() + .Set(GRPC_ARG_KEEPALIVE_TIME_MS, (20 * kPingInterval).millis()) + .Set(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, 0) + .Set(GRPC_ARG_HTTP2_BDP_PROBE, false)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(100); + Expect(100, true); + Step(); + IncomingCloseOnServer client_close; + s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close); + for (int i = 0; i < 30; i++) { + IncomingMessage server_message; + IncomingMessage client_message; + c.NewBatch(2).SendMessage("hello world").RecvMessage(server_message); + s.NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); + s.NewBatch(103).SendMessage("hello you"); + Expect(103, true); + Expect(2, true); + Step(); // Sleep for a short interval to check if the client sends any pings - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(kPingIntervalMS)); + Step(kPingInterval); } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_slice_unref(details); -} - -void keepalive_timeout(const CoreTestConfiguration& config) { - test_keepalive_timeout(config); - test_read_delays_keepalive(config); + c.NewBatch(3).SendCloseFromClient(); + s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + Expect(1, true); + Expect(3, true); + Expect(101, true); + Expect(104, true); + Step(); } -void keepalive_timeout_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/large_metadata.cc b/test/core/end2end/tests/large_metadata.cc index 28cef445a0d..6ae8adb512a 100644 --- a/test/core/end2end/tests/large_metadata.cc +++ b/test/core/end2end/tests/large_metadata.cc @@ -17,544 +17,211 @@ // #include -#include -#include -#include -#include +#include + +#include "absl/strings/string_view.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static grpc_status_code send_metadata(CoreTestFixture* f, - const size_t metadata_size, - grpc_slice* client_details) { - grpc_core::CqVerifier cqv(f->cq()); - grpc_call* c; - grpc_call* s; - grpc_metadata meta; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - int was_cancelled = 2; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - // Add metadata of size `metadata_size`. - meta.key = grpc_slice_from_static_string("key"); - meta.value = grpc_slice_malloc(metadata_size); - memset(GRPC_SLICE_START_PTR(meta.value), 'a', metadata_size); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - // Client: wait on initial metadata from server. - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = client_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - // Server: send metadata of size `metadata_size`. - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &meta; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_slice_unref(meta.value); - - return status; -} +namespace grpc_core { +namespace { + +class LargeMetadataTest { + public: + LargeMetadataTest(Http2SingleHopTest& test, const ChannelArgs& args) + : test_(test) { + test_.InitClient(args); + test_.InitServer(args); + } + + int PerformRequests(size_t metadata_size, int count) { + int num_requests_accepted = 0; + for (int i = 0; i < count; ++i) { + auto status = PerformOneRequest(metadata_size); + if (status.status() == GRPC_STATUS_RESOURCE_EXHAUSTED) { + EXPECT_THAT( + status.message(), + ::testing::StartsWith("received initial metadata size exceeds")); + } else { + num_requests_accepted++; + EXPECT_EQ(status.status(), GRPC_STATUS_OK); + EXPECT_EQ(status.message(), "xyz"); + } + } + return num_requests_accepted; + } + + private: + CoreEnd2endTest::IncomingStatusOnClient PerformOneRequest( + const size_t metadata_size) { + auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test_.RequestCall(101); + test_.Expect(101, true); + test_.Step(); + // Server: send metadata of size `metadata_size`. + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({{"key", std::string(metadata_size, 'a')}}) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test_.Expect(102, true); + test_.Expect(1, true); + test_.Step(); + return server_status; + } + + Http2SingleHopTest& test_; +}; // Server responds with metadata under soft limit of what client accepts. No // requests should be rejected. -static void test_request_with_large_metadata_under_soft_limit( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataUnderSoftLimit) { const size_t soft_limit = 32 * 1024; const size_t hard_limit = 45 * 1024; const size_t metadata_size = soft_limit; - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = - begin_test(config, "test_request_with_large_metadata_under_soft_limit", - &args, &args); - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = send_metadata(f.get(), metadata_size, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } + LargeMetadataTest test( + *this, ChannelArgs() + .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024) + .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024)); + EXPECT_EQ(test.PerformRequests(metadata_size, 100), 100); } // Server responds with metadata between soft and hard limits of what client // accepts. Some requests should be rejected. -static void test_request_with_large_metadata_between_soft_and_hard_limits( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataBetweenSoftAndHardLimits) { const size_t soft_limit = 32 * 1024; const size_t hard_limit = 45 * 1024; const size_t metadata_size = (soft_limit + hard_limit) / 2; - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, "test_request_with_large_metadata_between_soft_and_hard_limits", - &args, &args); - - int num_requests_rejected = 0; - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = send_metadata(f.get(), metadata_size, &client_details); - if (status == GRPC_STATUS_RESOURCE_EXHAUSTED) { - num_requests_rejected++; - const char* expected_error = - "received initial metadata size exceeds soft limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - } else { - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - } - grpc_slice_unref(client_details); - } - - // Check that some requests were rejected. - GPR_ASSERT(abs(num_requests_rejected - 50) <= 45); + LargeMetadataTest test( + *this, ChannelArgs() + .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024) + .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024)); + EXPECT_THAT(test.PerformRequests(metadata_size, 100), + ::testing::AllOf(::testing::Ge(5), ::testing::Le(95))); } // Server responds with metadata above hard limit of what the client accepts. // All requests should be rejected. -static void test_request_with_large_metadata_above_hard_limit( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataAboveHardLimit) { const size_t soft_limit = 32 * 1024; const size_t hard_limit = 45 * 1024; - const size_t metadata_size = hard_limit * 1.5; - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = - begin_test(config, "test_request_with_large_metadata_above_hard_limit", - &args, &args); - - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = send_metadata(f.get(), metadata_size, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } + const size_t metadata_size = hard_limit * 3 / 2; + LargeMetadataTest test( + *this, ChannelArgs() + .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024) + .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024)); + EXPECT_EQ(test.PerformRequests(metadata_size, 100), 0); } // Set soft limit higher than hard limit. All requests above hard limit should // be rejected, all requests below hard limit should be accepted (soft limit // should not be respected). -static void test_request_with_large_metadata_soft_limit_above_hard_limit( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataSoftLimitAboveHardLimit) { const size_t soft_limit = 64 * 1024; const size_t hard_limit = 32 * 1024; const size_t metadata_size_below_hard_limit = hard_limit; const size_t metadata_size_above_hard_limit = hard_limit * 2; - grpc_arg arg[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, "test_request_with_large_metadata_soft_limit_above_hard_limit", - &args, &args); - + LargeMetadataTest test( + *this, ChannelArgs() + .Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024) + .Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, hard_limit + 1024)); // Send 50 requests below hard limit. Should be accepted. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_below_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } - + EXPECT_EQ(test.PerformRequests(metadata_size_below_hard_limit, 50), 50); // Send 50 requests above hard limit. Should be rejected. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_above_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } + EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0); } // Set soft limit * 1.25 higher than default hard limit and do not set hard // limit. Soft limit * 1.25 should be used as hard limit. -static void test_request_with_large_metadata_soft_limit_overrides_default_hard( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, + RequestWithLargeMetadataSoftLimitOverridesDefaultHard) { const size_t soft_limit = 64 * 1024; const size_t metadata_size_below_soft_limit = soft_limit; const size_t metadata_size_above_hard_limit = soft_limit * 1.5; const size_t metadata_size_between_limits = (soft_limit + soft_limit * 1.25) / 2; - grpc_arg arg[] = {grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, - "test_request_with_large_metadata_soft_limit_overrides_default_hard", - &args, &args); - + LargeMetadataTest test( + *this, ChannelArgs().Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)); // Send 50 requests below soft limit. Should be accepted. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_below_soft_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } - + EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50); // Send 100 requests between soft and hard limits. Some should be rejected. - int num_requests_rejected = 0; - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_between_limits, &client_details); - if (status == GRPC_STATUS_RESOURCE_EXHAUSTED) { - num_requests_rejected++; - const char* expected_error = - "received initial metadata size exceeds soft limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - } else { - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - } - grpc_slice_unref(client_details); - } - // Check that some requests were rejected. - GPR_ASSERT(abs(num_requests_rejected - 50) <= 45); - + EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100), + ::testing::AllOf(::testing::Ge(5), ::testing::Le(95))); // Send 50 requests above hard limit. Should be rejected. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_above_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } + EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0); } // Set hard limit * 0.8 higher than default soft limit and do not set soft // limit. Hard limit * 0.8 should be used as soft limit. -static void test_request_with_large_metadata_hard_limit_overrides_default_soft( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, + RequestWithLargeMetadataHardLimitOverridsDefaultSoft) { const size_t hard_limit = 45 * 1024; const size_t metadata_size_below_soft_limit = hard_limit * 0.5; const size_t metadata_size_above_hard_limit = hard_limit * 1.5; const size_t metadata_size_between_limits = (hard_limit * 0.8 + hard_limit) / 2; - grpc_arg arg[] = {grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, - "test_request_with_large_metadata_hard_limit_overrides_default_soft", - &args, &args); - + LargeMetadataTest test(*this, + ChannelArgs().Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, + hard_limit + 1024)); // Send 50 requests below soft limit. Should be accepted. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_below_soft_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } - + EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50); // Send 100 requests between soft and hard limits. Some should be rejected. - int num_requests_rejected = 0; - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_between_limits, &client_details); - if (status == GRPC_STATUS_RESOURCE_EXHAUSTED) { - num_requests_rejected++; - const char* expected_error = - "received initial metadata size exceeds soft limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - } else { - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - } - grpc_slice_unref(client_details); - } - // Check that some requests were rejected. - GPR_ASSERT(abs(num_requests_rejected - 50) <= 45); - + EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100), + ::testing::AllOf(::testing::Ge(5), ::testing::Le(95))); // Send 50 requests above hard limit. Should be rejected. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_above_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } + EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0); } // Set hard limit lower than default hard limit and ensure new limit is // respected. Default soft limit is not respected since hard limit is lower than // soft limit. -static void test_request_with_large_metadata_hard_limit_below_default_hard( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataHardLimitBelowDefaultHard) { const size_t hard_limit = 4 * 1024; const size_t metadata_size_below_hard_limit = hard_limit; const size_t metadata_size_above_hard_limit = hard_limit * 2; - grpc_arg arg[] = {grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE), - hard_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, "test_request_with_large_metadata_hard_limit_below_default_hard", - &args, &args); - + LargeMetadataTest test(*this, + ChannelArgs().Set(GRPC_ARG_ABSOLUTE_MAX_METADATA_SIZE, + hard_limit + 1024)); // Send 50 requests below hard limit. Should be accepted. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_below_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } - + EXPECT_EQ(test.PerformRequests(metadata_size_below_hard_limit, 50), 50); // Send 50 requests above hard limit. Should be rejected. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_above_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } + EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0); } // Set soft limit lower than default soft limit and ensure new limit is // respected. Hard limit should be default hard since this is greater than 2 * // soft limit. -static void test_request_with_large_metadata_soft_limit_below_default_soft( - const CoreTestConfiguration& config) { +TEST_P(Http2SingleHopTest, RequestWithLargeMetadataSoftLimitBelowDefaultSoft) { const size_t soft_limit = 1 * 1024; const size_t metadata_size_below_soft_limit = soft_limit; // greater than 2 * soft, less than default hard const size_t metadata_size_between_limits = 10 * 1024; const size_t metadata_size_above_hard_limit = 75 * 1024; - grpc_arg arg[] = {grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_METADATA_SIZE), soft_limit + 1024)}; - grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg}; - auto f = begin_test( - config, "test_request_with_large_metadata_soft_limit_below_default_soft", - &args, &args); - + LargeMetadataTest test( + *this, ChannelArgs().Set(GRPC_ARG_MAX_METADATA_SIZE, soft_limit + 1024)); // Send 50 requests below soft limit. Should be accepted. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_below_soft_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - grpc_slice_unref(client_details); - } - + EXPECT_EQ(test.PerformRequests(metadata_size_below_soft_limit, 50), 50); // Send 100 requests between soft and hard limits. Some should be rejected. - int num_requests_rejected = 0; - for (int i = 0; i < 100; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_between_limits, &client_details); - if (status == GRPC_STATUS_RESOURCE_EXHAUSTED) { - num_requests_rejected++; - const char* expected_error = - "received initial metadata size exceeds soft limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - } else { - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(client_details, "xyz")); - } - grpc_slice_unref(client_details); - } - // Check that some requests were rejected. - GPR_ASSERT((abs(num_requests_rejected - 50) <= 49)); - + EXPECT_THAT(test.PerformRequests(metadata_size_between_limits, 100), + ::testing::AllOf(::testing::Ge(1), ::testing::Le(99))); // Send 50 requests above hard limit. Should be rejected. - for (int i = 0; i < 50; i++) { - grpc_slice client_details; - auto status = - send_metadata(f.get(), metadata_size_above_hard_limit, &client_details); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - const char* expected_error = - "received initial metadata size exceeds hard limit"; - grpc_slice actual_error = - grpc_slice_split_head(&client_details, strlen(expected_error)); - GPR_ASSERT(0 == grpc_slice_str_cmp(actual_error, expected_error)); - grpc_slice_unref(actual_error); - grpc_slice_unref(client_details); - } -} - -void large_metadata(const CoreTestConfiguration& config) { - test_request_with_large_metadata_under_soft_limit(config); - // TODO(yashykt): Maybe add checks for metadata size in inproc transport too. - if (strcmp(config.name, "inproc") != 0) { - test_request_with_large_metadata_between_soft_and_hard_limits(config); - test_request_with_large_metadata_above_hard_limit(config); - test_request_with_large_metadata_soft_limit_above_hard_limit(config); - test_request_with_large_metadata_soft_limit_overrides_default_hard(config); - test_request_with_large_metadata_hard_limit_overrides_default_soft(config); - test_request_with_large_metadata_hard_limit_below_default_hard(config); - test_request_with_large_metadata_soft_limit_below_default_soft(config); - } + EXPECT_EQ(test.PerformRequests(metadata_size_above_hard_limit, 50), 0); } -void large_metadata_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/load_reporting_hook.cc b/test/core/end2end/tests/load_reporting_hook.cc deleted file mode 100644 index 4ad8bf33ab2..00000000000 --- a/test/core/end2end/tests/load_reporting_hook.cc +++ /dev/null @@ -1,266 +0,0 @@ -// -// -// Copyright 2016 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 - -#include -#include -#include -#include -#include -#include - -#include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" -#include "src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/crash.h" -#include "test/core/end2end/cq_verifier.h" -#include "test/core/end2end/end2end_tests.h" - -enum { TIMEOUT = 200000 }; - -static void* tag(intptr_t t) { return (void*)t; } - -typedef struct { - gpr_mu mu; - intptr_t channel_id; - intptr_t call_id; - - char* initial_md_str; - char* trailing_md_str; - char* method_name; - - uint64_t incoming_bytes; - uint64_t outgoing_bytes; - - grpc_status_code call_final_status; - - bool fully_processed; -} load_reporting_data; - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - - return f; -} - -static void request_response_with_payload( - const CoreTestConfiguration& config, CoreTestFixture f, - const char* method_name, const char* request_msg, const char* response_msg, - grpc_metadata* initial_lr_metadata, grpc_metadata* trailing_lr_metadata) { - grpc_slice request_payload_slice = grpc_slice_from_static_string(request_msg); - grpc_slice response_payload_slice = - grpc_slice_from_static_string(response_msg); - grpc_call* c; - grpc_call* s; - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string(method_name), nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - GPR_ASSERT(initial_lr_metadata != nullptr); - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = initial_lr_metadata; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - GPR_ASSERT(trailing_lr_metadata != nullptr); - op->data.send_status_from_server.trailing_metadata_count = 1; - op->data.send_status_from_server.trailing_metadata = trailing_lr_metadata; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -// override the default for testing purposes -extern void (*g_load_reporting_fn)( - const grpc_load_reporting_call_data* call_data); - -static void test_load_reporting_hook(const CoreTestConfiguration& config) { - // TODO(dgq): this test is currently a noop until LR is fully defined. - // Leaving the rest here, as it'll likely be reusable. - - // Introduce load reporting for the server through its arguments - grpc_arg arg = grpc_load_reporting_enable_arg(); - grpc_channel_args* lr_server_args = - grpc_channel_args_copy_and_add(nullptr, &arg, 1); - - auto f = - begin_test(config, "test_load_reporting_hook", nullptr, lr_server_args); - - const char* method_name = "/gRPCFTW"; - const char* request_msg = "the msg from the client"; - const char* response_msg = "... and the response from the server"; - - grpc_metadata initial_lr_metadata; - grpc_metadata trailing_lr_metadata; - - initial_lr_metadata.key = GRPC_MDSTR_LB_TOKEN; - initial_lr_metadata.value = grpc_slice_from_static_string("client-token"); - memset(&initial_lr_metadata.internal_data, 0, - sizeof(initial_lr_metadata.internal_data)); - - trailing_lr_metadata.key = GRPC_MDSTR_LB_COST_BIN; - trailing_lr_metadata.value = grpc_slice_from_static_string("server-token"); - memset(&trailing_lr_metadata.internal_data, 0, - sizeof(trailing_lr_metadata.internal_data)); - - request_response_with_payload(config, f, method_name, request_msg, - response_msg, &initial_lr_metadata, - &trailing_lr_metadata); - - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(lr_server_args); - } -} - -void load_reporting_hook(const CoreTestConfiguration& config) { - test_load_reporting_hook(config); -} - -void load_reporting_hook_pre_init(void) {} diff --git a/test/core/end2end/tests/max_concurrent_streams.cc b/test/core/end2end/tests/max_concurrent_streams.cc index 24915ccd726..aa16ad9d1dc 100644 --- a/test/core/end2end/tests/max_concurrent_streams.cc +++ b/test/core/end2end/tests/max_concurrent_streams.cc @@ -16,769 +16,222 @@ // // -#include -#include - -#include -#include +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +namespace grpc_core { +namespace { + +void SimpleRequestBody(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -static void test_max_concurrent_streams(const CoreTestConfiguration& config) { - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call* c1; - grpc_call* c2; - grpc_call* s1; - grpc_call* s2; - int live_call; - gpr_timespec deadline; - grpc_event ev; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1; - grpc_status_code status2; - grpc_slice details2; - grpc_op ops[6]; - grpc_op* op; - int was_cancelled; - int got_client_start; - int got_server_start; - - server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - auto f = - begin_test(config, "test_max_concurrent_streams", nullptr, &server_args); - grpc_core::CqVerifier cqv(f->cq()); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - +TEST_P(Http2SingleHopTest, MaxConcurrentStreams) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)); + InitClient(ChannelArgs()); // perform a ping-pong to ensure that settings have had a chance to round // trip - simple_request_body(config, f.get()); + SimpleRequestBody(*this); // perform another one to make sure that the one stream case still works - simple_request_body(config, f.get()); - + SimpleRequestBody(*this); // start two requests - ensuring that the second is not accepted until // the first completes - deadline = grpc_timeout_seconds_to_deadline(1000); - c1 = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/alpha"), nullptr, deadline, nullptr); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/beta"), - nullptr, deadline, nullptr); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s1, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(301), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(302), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(401), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(402), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - got_client_start = 0; - got_server_start = 0; - live_call = -1; - while (!got_client_start || !got_server_start) { - ev = grpc_completion_queue_next( - f->cq(), grpc_timeout_seconds_to_deadline(3), nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.success); - if (ev.tag == grpc_core::CqVerifier::tag(101)) { - GPR_ASSERT(!got_server_start); - got_server_start = 1; - } else { - GPR_ASSERT(!got_client_start); - GPR_ASSERT(ev.tag == grpc_core::CqVerifier::tag(301) || - ev.tag == grpc_core::CqVerifier::tag(401)); - // The /alpha or /beta calls started above could be invoked (but NOT - // both); - // check this here - // We'll get tag 303 or 403, we want 300, 400 - live_call = (static_cast(reinterpret_cast(ev.tag))) - 1; - got_client_start = 1; - } + auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(1000)).Create(); + auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(1000)).Create(); + auto s1 = RequestCall(101); + c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata1; + IncomingStatusOnClient server_status1; + c1.NewBatch(302) + .RecvStatusOnClient(server_status1) + .RecvInitialMetadata(server_initial_metadata1); + c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata2; + IncomingStatusOnClient server_status2; + c2.NewBatch(402) + .RecvStatusOnClient(server_status2) + .RecvInitialMetadata(server_initial_metadata2); + bool got_client_start = false; + bool got_server_start = false; + int live_call; + Expect(101, MaybePerformAction{[&got_server_start](bool ok) { + EXPECT_TRUE(ok); + got_server_start = ok; + }}); + Expect(301, MaybePerformAction{[&got_client_start, &live_call](bool ok) { + EXPECT_FALSE(got_client_start); + EXPECT_TRUE(ok); + got_client_start = ok; + live_call = 300; + }}); + Expect(401, MaybePerformAction{[&got_client_start, &live_call](bool ok) { + EXPECT_FALSE(got_client_start); + EXPECT_TRUE(ok); + got_client_start = ok; + live_call = 400; + }}); + Step(); + if (got_client_start && !got_server_start) { + Expect(101, true); + Step(); + got_server_start = true; + } else if (got_server_start && !got_client_start) { + Expect(301, MaybePerformAction{[&got_client_start, &live_call](bool ok) { + EXPECT_FALSE(got_client_start); + EXPECT_TRUE(ok); + got_client_start = ok; + live_call = 300; + }}); + Expect(401, MaybePerformAction{[&got_client_start, &live_call](bool ok) { + EXPECT_FALSE(got_client_start); + EXPECT_TRUE(ok); + got_client_start = ok; + live_call = 400; + }}); + Step(); + EXPECT_TRUE(got_client_start); } - GPR_ASSERT(live_call == 300 || live_call == 400); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(live_call + 2), true); + IncomingCloseOnServer client_close; + s1.NewBatch(102) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + Expect(102, true); + Expect(live_call + 2, true); // first request is finished, we should be able to start the second live_call = (live_call == 300) ? 400 : 300; - cqv.Expect(grpc_core::CqVerifier::tag(live_call + 1), true); - cqv.Verify(); - - grpc_call_details_destroy(&call_details); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s2, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201))); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(live_call + 2), true); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Verify(); - - grpc_call_unref(c1); - grpc_call_unref(s1); - grpc_call_unref(c2); - grpc_call_unref(s2); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); + Expect(live_call + 1, true); + Step(); + auto s2 = RequestCall(201); + Expect(201, true); + Step(); + s2.NewBatch(202) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + Expect(live_call + 2, true); + Expect(202, true); + Step(); } -static void test_max_concurrent_streams_with_timeout_on_first( - const CoreTestConfiguration& config) { - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call* c1; - grpc_call* c2; - grpc_call* s1; - grpc_call* s2; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1 = grpc_empty_slice(); - grpc_status_code status2; - grpc_slice details2 = grpc_empty_slice(); - grpc_op ops[6]; - grpc_op* op; - int was_cancelled; - - server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - auto f = - begin_test(config, "test_max_concurrent_streams_with_timeout_on_first", - nullptr, &server_args); - grpc_core::CqVerifier cqv(f->cq()); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - +TEST_P(Http2SingleHopTest, MaxConcurrentStreamsTimeoutOnFirst) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)); + InitClient(ChannelArgs()); // perform a ping-pong to ensure that settings have had a chance to round // trip - simple_request_body(config, f.get()); + SimpleRequestBody(*this); // perform another one to make sure that the one stream case still works - simple_request_body(config, f.get()); - + SimpleRequestBody(*this); // start two requests - ensuring that the second is not accepted until // the first completes - c1 = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/alpha"), nullptr, - grpc_timeout_seconds_to_deadline(3), nullptr); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/beta"), - nullptr, grpc_timeout_seconds_to_deadline(1000), - nullptr); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s1, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(301), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(302), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(301), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(401), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv2; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(402), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s2, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201))); - - cqv.Expect(grpc_core::CqVerifier::tag(302), true); + auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(3)).Create(); + auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(1000)).Create(); + auto s1 = RequestCall(101); + c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata1; + IncomingStatusOnClient server_status1; + c1.NewBatch(302) + .RecvStatusOnClient(server_status1) + .RecvInitialMetadata(server_initial_metadata1); + Expect(101, true); + Expect(301, true); + Step(); + c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata2; + IncomingStatusOnClient server_status2; + c2.NewBatch(402) + .RecvStatusOnClient(server_status2) + .RecvInitialMetadata(server_initial_metadata2); + auto s2 = RequestCall(201); + Expect(302, true); // first request is finished, we should be able to start the second - cqv.Expect(grpc_core::CqVerifier::tag(401), true); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(402), true); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Verify(); - - grpc_call_unref(c1); - grpc_call_unref(s1); - grpc_call_unref(c2); - grpc_call_unref(s2); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); + Expect(401, true); + Expect(201, true); + Step(); + IncomingCloseOnServer client_close2; + s2.NewBatch(202) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close2) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + Expect(402, true); + Expect(202, true); + Step(); } -static void test_max_concurrent_streams_with_timeout_on_second( - const CoreTestConfiguration& config) { - grpc_arg server_arg; - grpc_channel_args server_args; - grpc_call* c1; - grpc_call* c2; - grpc_call* s1; - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array initial_metadata_recv1; - grpc_metadata_array trailing_metadata_recv1; - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array trailing_metadata_recv2; - grpc_status_code status1; - grpc_call_error error; - grpc_slice details1 = grpc_empty_slice(); - grpc_status_code status2; - grpc_slice details2 = grpc_empty_slice(); - grpc_op ops[6]; - grpc_op* op; - int was_cancelled; - - server_arg.key = const_cast(GRPC_ARG_MAX_CONCURRENT_STREAMS); - server_arg.type = GRPC_ARG_INTEGER; - server_arg.value.integer = 1; - - server_args.num_args = 1; - server_args.args = &server_arg; - - auto f = - begin_test(config, "test_max_concurrent_streams_with_timeout_on_second", - nullptr, &server_args); - grpc_core::CqVerifier cqv(f->cq()); - - grpc_metadata_array_init(&request_metadata_recv); - grpc_metadata_array_init(&initial_metadata_recv1); - grpc_metadata_array_init(&trailing_metadata_recv1); - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_call_details_init(&call_details); - +TEST_P(Http2SingleHopTest, MaxConcurrentStreamsTimeoutOnSecond) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1)); + InitClient(ChannelArgs()); // perform a ping-pong to ensure that settings have had a chance to round // trip - simple_request_body(config, f.get()); + SimpleRequestBody(*this); // perform another one to make sure that the one stream case still works - simple_request_body(config, f.get()); - + SimpleRequestBody(*this); // start two requests - ensuring that the second is not accepted until // the first completes , and the second request will timeout in the // concurrent_list - c1 = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/alpha"), nullptr, - grpc_timeout_seconds_to_deadline(1000), nullptr); - GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/beta"), - nullptr, grpc_timeout_seconds_to_deadline(3), - nullptr); - GPR_ASSERT(c2); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s1, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(301), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv1; - op->data.recv_status_on_client.status = &status1; - op->data.recv_status_on_client.status_details = &details1; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv1; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(302), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(301), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(401), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv2; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(402), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + auto c1 = NewClientCall("/alpha").Timeout(Duration::Seconds(1000)).Create(); + auto c2 = NewClientCall("/beta").Timeout(Duration::Seconds(3)).Create(); + auto s1 = RequestCall(101); + c1.NewBatch(301).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata1; + IncomingStatusOnClient server_status1; + c1.NewBatch(302) + .RecvStatusOnClient(server_status1) + .RecvInitialMetadata(server_initial_metadata1); + Expect(101, true); + Expect(301, true); + Step(); + c2.NewBatch(401).SendInitialMetadata({}).SendCloseFromClient(); + IncomingMetadata server_initial_metadata2; + IncomingStatusOnClient server_status2; + c2.NewBatch(402) + .RecvStatusOnClient(server_status2) + .RecvInitialMetadata(server_initial_metadata2); // the second request is time out - cqv.Expect(grpc_core::CqVerifier::tag(401), false); - cqv.Expect(grpc_core::CqVerifier::tag(402), true); - cqv.Verify(); - - // second request is finished because of time out, so destroy the second call - // - grpc_call_unref(c2); - + Expect(401, false); + Expect(402, true); + Step(); // now reply the first call - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s1, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(302), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(c1); - grpc_call_unref(s1); - - grpc_slice_unref(details1); - grpc_slice_unref(details2); - grpc_metadata_array_destroy(&initial_metadata_recv1); - grpc_metadata_array_destroy(&trailing_metadata_recv1); - grpc_metadata_array_destroy(&initial_metadata_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); -} - -void max_concurrent_streams(const CoreTestConfiguration& config) { - test_max_concurrent_streams_with_timeout_on_first(config); - test_max_concurrent_streams_with_timeout_on_second(config); - test_max_concurrent_streams(config); + IncomingCloseOnServer client_close1; + s1.NewBatch(102) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close1) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + Expect(302, true); + Expect(102, true); + Step(); } -void max_concurrent_streams_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/max_connection_age.cc b/test/core/end2end/tests/max_connection_age.cc index 0e4c1c433c5..4b45b9ba44c 100644 --- a/test/core/end2end/tests/max_connection_age.cc +++ b/test/core/end2end/tests/max_connection_age.cc @@ -17,21 +17,14 @@ // #include -#include -#include -#include +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/time.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/util/test_config.h" @@ -52,311 +45,124 @@ // The grace period for the test to observe the channel shutdown process #define IMMEDIATE_SHUTDOWN_GRACE_TIME_MS 3000 -static void test_max_age_forcibly_close(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - auto cqv = std::make_unique(f->cq()); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, MAX_CONNECTION_AGE_MS) - .Set(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, - MAX_CONNECTION_AGE_GRACE_MS) - .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, MAX_CONNECTION_IDLE_MS); - - f->InitClient(grpc_core::ChannelArgs()); - f->InitServer(server_args); - - grpc_call* c; - grpc_call* s = nullptr; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - grpc_event ev = grpc_completion_queue_next( - f->cq(), gpr_inf_future(GPR_CLOCK_MONOTONIC), nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == grpc_core::CqVerifier::tag(1) || - ev.tag == grpc_core::CqVerifier::tag(101)); - - if (ev.tag == grpc_core::CqVerifier::tag(101)) { +namespace grpc_core { +namespace { + +TEST_P(Http2Test, MaxAgeForciblyClose) { + SKIP_IF_MINSTACK(); + InitClient(ChannelArgs()); + InitServer(ChannelArgs() + .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, MAX_CONNECTION_AGE_MS) + .Set(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, + MAX_CONNECTION_AGE_GRACE_MS) + .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, MAX_CONNECTION_IDLE_MS)); + auto c = NewClientCall("/foo") + .Timeout(Duration::Seconds(CALL_DEADLINE_S)) + .Create(); + const auto expect_shutdown_time = + Timestamp::FromTimespecRoundUp(grpc_timeout_milliseconds_to_deadline( + static_cast(MAX_CONNECTION_AGE_MS * + MAX_CONNECTION_AGE_JITTER_MULTIPLIER) + + MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS)); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + bool got_client = false; + bool got_server = false; + Expect(1, Maybe{&got_client}); + Expect(101, Maybe{&got_server}); + Step(); + if (got_server) { // Request got through to the server before connection timeout - // Wait for the channel to reach its max age - cqv->VerifyEmpty( - grpc_core::Duration::Seconds(CQ_MAX_CONNECTION_AGE_WAIT_TIME_S)); - + Step(Duration::Seconds(CQ_MAX_CONNECTION_AGE_WAIT_TIME_S)); // After the channel reaches its max age, we still do nothing here. And wait // for it to use up its max age grace period. - cqv->Expect(grpc_core::CqVerifier::tag(1), true); - cqv->Verify(); - - gpr_timespec expect_shutdown_time = grpc_timeout_milliseconds_to_deadline( - static_cast(MAX_CONNECTION_AGE_MS * - MAX_CONNECTION_AGE_JITTER_MULTIPLIER) + - MAX_CONNECTION_AGE_GRACE_MS + IMMEDIATE_SHUTDOWN_GRACE_TIME_MS); - - gpr_timespec channel_shutdown_time = gpr_now(GPR_CLOCK_MONOTONIC); - GPR_ASSERT(gpr_time_cmp(channel_shutdown_time, expect_shutdown_time) < 0); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv->Expect(grpc_core::CqVerifier::tag(102), true); - cqv->Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 1); + Expect(1, true); + Step(); + EXPECT_LT(Timestamp::Now(), expect_shutdown_time); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_TRUE(client_close.was_cancelled()); } else { // Request failed before getting to the server } - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv->Expect(grpc_core::CqVerifier::tag(0xdead), true); - if (s == nullptr) { - cqv->Expect(grpc_core::CqVerifier::tag(101), false); - } - cqv->Verify(); - - if (s != nullptr) { - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); + ShutdownServerAndNotify(1000); + Expect(1000, true); + if (got_client) { + Expect(101, false); } - + Step(); // The connection should be closed immediately after the max age grace period, // the in-progress RPC should fail. - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(c); - cqv.reset(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); } -static void test_max_age_gracefully_close(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - auto cqv = std::make_unique(f->cq()); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, MAX_CONNECTION_AGE_MS) - .Set(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, INT_MAX) - .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, MAX_CONNECTION_IDLE_MS); - - f->InitClient(grpc_core::ChannelArgs()); - f->InitServer(server_args); - - grpc_call* c; - grpc_call* s = nullptr; - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(CALL_DEADLINE_S); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - - grpc_event ev = grpc_completion_queue_next( - f->cq(), gpr_inf_future(GPR_CLOCK_MONOTONIC), nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - GPR_ASSERT(ev.tag == grpc_core::CqVerifier::tag(1) || - ev.tag == grpc_core::CqVerifier::tag(101)); - - if (ev.tag == grpc_core::CqVerifier::tag(101)) { +TEST_P(Http2Test, MaxAgeGracefullyClose) { + SKIP_IF_MINSTACK(); + InitClient(ChannelArgs()); + InitServer(ChannelArgs() + .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, MAX_CONNECTION_AGE_MS) + .Set(GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS, INT_MAX) + .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, MAX_CONNECTION_IDLE_MS)); + auto c = NewClientCall("/foo") + .Timeout(Duration::Seconds(CALL_DEADLINE_S)) + .Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + bool got_client = false; + bool got_server = false; + Expect(1, Maybe{&got_client}); + Expect(101, Maybe{&got_server}); + Step(); + if (got_server) { // Request got through to the server before connection timeout - // Wait for the channel to reach its max age - cqv->VerifyEmpty( - grpc_core::Duration::Seconds(CQ_MAX_CONNECTION_AGE_WAIT_TIME_S)); - + Step(Duration::Seconds(CQ_MAX_CONNECTION_AGE_WAIT_TIME_S)); // The connection is shutting down gracefully. In-progress rpc should not be // closed, hence the completion queue should see nothing here. - cqv->VerifyEmpty( - grpc_core::Duration::Seconds(CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S)); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv->Expect(grpc_core::CqVerifier::tag(102), true); - cqv->Expect(grpc_core::CqVerifier::tag(1), true); - cqv->Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); + Step(Duration::Seconds(CQ_MAX_CONNECTION_AGE_GRACE_WAIT_TIME_S)); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } else { // Request failed before getting to the server } - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv->Expect(grpc_core::CqVerifier::tag(0xdead), true); - if (s == nullptr) { - cqv->Expect(grpc_core::CqVerifier::tag(101), false); - } - cqv->Verify(); - - if (s != nullptr) { - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); + ShutdownServerAndNotify(1000); + Expect(1000, true); + if (got_client) { + Expect(101, false); } - + Step(); // The connection is closed gracefully with goaway, the rpc should still be // completed. - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_unref(c); - cqv.reset(); -} - -void max_connection_age(const CoreTestConfiguration& config) { - test_max_age_forcibly_close(config); - test_max_age_gracefully_close(config); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); } -void max_connection_age_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/max_connection_idle.cc b/test/core/end2end/tests/max_connection_idle.cc index 7b435777755..3af51f7cdee 100644 --- a/test/core/end2end/tests/max_connection_idle.cc +++ b/test/core/end2end/tests/max_connection_idle.cc @@ -16,205 +16,94 @@ // // -#include - -#include -#include +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -#define MAX_CONNECTION_IDLE_MS 2000 -#define MAX_CONNECTION_AGE_MS 9999 - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(30); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY | - GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +namespace grpc_core { +namespace { + +void SimpleRequestBody(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(30)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata( + {}, GRPC_INITIAL_METADATA_WAIT_FOR_READY | + GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -static void test_max_connection_idle(const CoreTestConfiguration& config) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_connectivity_state state = GRPC_CHANNEL_IDLE; - grpc_core::CqVerifier cqv(f->cq()); - - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, MAX_CONNECTION_IDLE_MS) - .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, MAX_CONNECTION_AGE_MS); - - f->InitClient(client_args); - f->InitServer(server_args); - +TEST_P(RetryHttp2Test, MaxConnectionIdle) { + const auto kMaxConnectionIdle = Duration::Seconds(2); + const auto kMaxConnectionAge = Duration::Seconds(10); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, + Duration::Seconds(1).millis()) + .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, Duration::Seconds(1).millis()) + .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, + Duration::Seconds(5).millis())); + InitServer( + ChannelArgs() + .Set(GRPC_ARG_MAX_CONNECTION_IDLE_MS, kMaxConnectionIdle.millis()) + .Set(GRPC_ARG_MAX_CONNECTION_AGE_MS, kMaxConnectionAge.millis())); // check that we're still in idle, and start connecting - GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 1) == - GRPC_CHANNEL_IDLE); + grpc_connectivity_state state = CheckConnectivityState(true); + EXPECT_EQ(state, GRPC_CHANNEL_IDLE); // we'll go through some set of transitions (some might be missed), until // READY is reached while (state != GRPC_CHANNEL_READY) { - grpc_channel_watch_connectivity_state( - f->client(), state, grpc_timeout_seconds_to_deadline(10), f->cq(), - grpc_core::CqVerifier::tag(99)); - cqv.Expect(grpc_core::CqVerifier::tag(99), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_READY || - state == GRPC_CHANNEL_CONNECTING || - state == GRPC_CHANNEL_TRANSIENT_FAILURE); + WatchConnectivityState(state, Duration::Seconds(10), 99); + Expect(99, true); + Step(); + state = CheckConnectivityState(false); + EXPECT_THAT(state, + ::testing::AnyOf(GRPC_CHANNEL_READY, GRPC_CHANNEL_CONNECTING, + GRPC_CHANNEL_TRANSIENT_FAILURE)); } - // Use a simple request to cancel and reset the max idle timer - simple_request_body(config, f.get()); - + SimpleRequestBody(*this); // wait for the channel to reach its maximum idle time - grpc_channel_watch_connectivity_state( - f->client(), GRPC_CHANNEL_READY, - gpr_time_add(grpc_timeout_milliseconds_to_deadline(3000), - gpr_time_from_millis(MAX_CONNECTION_IDLE_MS, GPR_TIMESPAN)), - f->cq(), grpc_core::CqVerifier::tag(99)); - cqv.Expect(grpc_core::CqVerifier::tag(99), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || - state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - cqv.Verify(); -} - -void max_connection_idle(const CoreTestConfiguration& config) { - test_max_connection_idle(config); + WatchConnectivityState(GRPC_CHANNEL_READY, + Duration::Seconds(3) + kMaxConnectionIdle, 99); + Expect(99, true); + Step(); + state = CheckConnectivityState(false); + EXPECT_THAT(state, + ::testing::AnyOf(GRPC_CHANNEL_IDLE, GRPC_CHANNEL_CONNECTING, + GRPC_CHANNEL_TRANSIENT_FAILURE)); + ShutdownServerAndNotify(1000); + Expect(1000, true); + Step(); } -void max_connection_idle_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/max_message_length.cc b/test/core/end2end/tests/max_message_length.cc index e57cc949cfe..cada91eddb4 100644 --- a/test/core/end2end/tests/max_message_length.cc +++ b/test/core/end2end/tests/max_message_length.cc @@ -16,731 +16,285 @@ // // -#include - -#include -#include #include -#include "absl/strings/match.h" +#include "absl/strings/string_view.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "\n\n\nRunning test: %s/%s client_args=%s server_args=%s", - test_name, config.name, - grpc_core::ChannelArgs::FromC(client_args).ToString().c_str(), - grpc_core::ChannelArgs::FromC(server_args).ToString().c_str()); - // We intentionally do not pass the client and server args to - // create_fixture(), since we don't want the limit enforced on the - // proxy, only on the backend server. - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; +using testing::StartsWith; + +namespace grpc_core { +namespace { + +void TestMaxMessageLengthOnClientOnRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/service/method").Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_EQ(server_status.message(), "Sent message larger than max (11 vs. 5)"); } -// Test with request larger than the limit. -// If send_limit is true, applies send limit on client; otherwise, applies -// recv limit on server. -static void test_max_message_length_on_request( - const CoreTestConfiguration& config, bool send_limit, - bool use_service_config, bool use_string_json_value) { - gpr_log(GPR_INFO, - "testing request with send_limit=%d use_service_config=%d " - "use_string_json_value=%d", - send_limit, use_service_config, use_string_json_value); - - grpc_call* c = nullptr; - grpc_call* s = nullptr; - grpc_op ops[6]; - grpc_op* op; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* recv_payload = nullptr; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_slice expect_in_details = grpc_slice_from_copied_string( - send_limit ? "Sent message larger than max (11 vs. 5)" - : "Received message larger than max (11 vs. 5)"); - int was_cancelled = 2; - - grpc_channel_args* client_args = nullptr; - grpc_channel_args* server_args = nullptr; - if (use_service_config) { - // We don't currently support service configs on the server side. - GPR_ASSERT(send_limit); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = - use_string_json_value - ? const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxRequestMessageBytes\": \"5\"\n" - " } ]\n" - "}") - : const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxRequestMessageBytes\": 5\n" - " } ]\n" - "}"); - client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); - } else { - // Set limit via channel args. - grpc_arg arg; - arg.key = send_limit - ? const_cast(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) - : const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 5; - grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); - if (send_limit) { - client_args = args; - } else { - server_args = args; - } - } - - auto f = begin_test(config, "test_max_request_message_length", client_args, - server_args); - { - grpc_core::ExecCtx exec_ctx; - if (client_args != nullptr) grpc_channel_args_destroy(client_args); - if (server_args != nullptr) grpc_channel_args_destroy(server_args); - } - - grpc_core::CqVerifier cqv(f->cq()); - - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, - gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - if (send_limit) { - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - goto done; - } - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &recv_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 1); - -done: - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT(grpc_slice_slice(details, expect_in_details) >= 0); - - grpc_slice_unref(details); - grpc_slice_unref(expect_in_details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(recv_payload); - - grpc_call_unref(c); - if (s != nullptr) grpc_call_unref(s); +void TestMaxMessageLengthOnServerOnRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/service/method").Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvCloseOnServer(client_close).RecvMessage(client_message); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_TRUE(client_close.was_cancelled()); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_EQ(server_status.message(), + "Received message larger than max (11 vs. 5)"); } -// Test with response larger than the limit. -// If send_limit is true, applies send limit on server; otherwise, applies -// recv limit on client. -static void test_max_message_length_on_response( - const CoreTestConfiguration& config, bool send_limit, - bool use_service_config, bool use_string_json_value) { - gpr_log(GPR_INFO, - "testing response with send_limit=%d use_service_config=%d " - "use_string_json_value=%d", - send_limit, use_service_config, use_string_json_value); - - grpc_call* c = nullptr; - grpc_call* s = nullptr; - grpc_op ops[6]; - grpc_op* op; - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* recv_payload = nullptr; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - grpc_slice expect_in_details = grpc_slice_from_copied_string( - send_limit ? "Sent message larger than max (11 vs. 5)" - : "Received message larger than max (11 vs. 5)"); - int was_cancelled = 2; - - grpc_channel_args* client_args = nullptr; - grpc_channel_args* server_args = nullptr; - if (use_service_config) { - // We don't currently support service configs on the server side. - GPR_ASSERT(!send_limit); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - use_string_json_value - ? "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxResponseMessageBytes\": \"5\"\n" - " } ]\n" - "}" - : "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"maxResponseMessageBytes\": 5\n" - " } ]\n" - "}"); - client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); - } else { - // Set limit via channel args. - grpc_arg arg; - arg.key = send_limit - ? const_cast(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) - : const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH); - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 5; - grpc_channel_args* args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); - if (send_limit) { - server_args = args; - } else { - client_args = args; - } - } - - auto f = begin_test(config, "test_max_response_message_length", client_args, - server_args); - { - grpc_core::ExecCtx exec_ctx; - if (client_args != nullptr) grpc_channel_args_destroy(client_args); - if (server_args != nullptr) grpc_channel_args_destroy(server_args); - } - grpc_core::CqVerifier cqv(f->cq()); - - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, - gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &recv_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +void TestMaxMessageLengthOnClientOnResponse(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/service/method").Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close) + .SendMessage("hello world") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_EQ(server_status.message(), + "Received message larger than max (11 vs. 5)"); +} - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); +void TestMaxMessageLengthOnServerOnResponse(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/service/method").Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .RecvCloseOnServer(client_close) + .SendMessage("hello world") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_EQ(server_status.message(), "Sent message larger than max (11 vs. 5)"); +} - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(CoreEnd2endTest, MaxMessageLengthOnClientOnRequestViaChannelArg) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, 5)); + TestMaxMessageLengthOnClientOnRequest(*this); +} - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); +TEST_P(CoreEnd2endTest, + MaxMessageLengthOnClientOnRequestViaServiceConfigWithStringJsonValue) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxRequestMessageBytes\": \"5\"\n" + " } ]\n" + "}")); + TestMaxMessageLengthOnClientOnRequest(*this); +} - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT(grpc_slice_slice(details, expect_in_details) >= 0); +TEST_P(CoreEnd2endTest, + MaxMessageLengthOnClientOnRequestViaServiceConfigWithIntegerJsonValue) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxRequestMessageBytes\": 5\n" + " } ]\n" + "}")); + TestMaxMessageLengthOnClientOnRequest(*this); +} - grpc_slice_unref(details); - grpc_slice_unref(expect_in_details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(recv_payload); +TEST_P(CoreEnd2endTest, MaxMessageLengthOnServerOnRequestViaChannelArg) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, 5)); + InitClient(ChannelArgs()); + TestMaxMessageLengthOnServerOnRequest(*this); +} - grpc_call_unref(c); - if (s != nullptr) grpc_call_unref(s); +TEST_P(CoreEnd2endTest, MaxMessageLengthOnClientOnResponseViaChannelArg) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, 5)); + TestMaxMessageLengthOnClientOnResponse(*this); } -static grpc_metadata gzip_compression_override() { - grpc_metadata gzip_compression_override; - gzip_compression_override.key = - grpc_slice_from_static_string("grpc-internal-encoding-request"); - gzip_compression_override.value = grpc_slice_from_static_string("gzip"); - memset(&gzip_compression_override.internal_data, 0, - sizeof(gzip_compression_override.internal_data)); - return gzip_compression_override; +TEST_P(CoreEnd2endTest, + MaxMessageLengthOnClientOnResponseViaServiceConfigWithStringJsonValue) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxResponseMessageBytes\": \"5\"\n" + " } ]\n" + "}")); + TestMaxMessageLengthOnClientOnResponse(*this); } -// Test receive message limit with compressed request larger than the limit -static void test_max_receive_message_length_on_compressed_request( - const CoreTestConfiguration& config) { - gpr_log(GPR_INFO, "test max receive message length on compressed request"); +TEST_P(CoreEnd2endTest, + MaxMessageLengthOnClientOnResponseViaServiceConfigWithIntegerJsonValue) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"maxResponseMessageBytes\": 5\n" + " } ]\n" + "}")); + TestMaxMessageLengthOnClientOnResponse(*this); +} - grpc_call* c = nullptr; - grpc_call* s = nullptr; - grpc_op ops[6]; - grpc_op* op; - grpc_slice request_payload_slice = grpc_slice_malloc(1024); - memset(GRPC_SLICE_START_PTR(request_payload_slice), 'a', 1024); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* recv_payload = nullptr; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; +TEST_P(CoreEnd2endTest, MaxMessageLengthOnServerOnResponseViaChannelArg) { + SKIP_IF_MINSTACK(); + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, 5)); + InitClient(ChannelArgs()); + TestMaxMessageLengthOnServerOnResponse(*this); +} +TEST_P(Http2Test, MaxMessageLengthOnServerOnRequestWithCompression) { + SKIP_IF_MINSTACK(); // Set limit via channel args. - grpc_arg arg[1]; - arg[0] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH), 5); - grpc_channel_args* server_args = - grpc_channel_args_copy_and_add(nullptr, arg, 1); - - auto f = begin_test(config, "test_max_request_message_length", nullptr, - server_args); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(server_args); - } - grpc_core::CqVerifier cqv(f->cq()); - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, - gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - grpc_metadata compression_md = gzip_compression_override(); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &compression_md; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &recv_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + InitServer(ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, 5)); + InitClient(ChannelArgs()); + auto c = NewClientCall("/service/method").Create(); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({{"grpc-internal-encoding-request", "gzip"}}) + .SendMessage(std::string(1024, 'a')) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + IncomingMessage client_message; + IncomingCloseOnServer client_close; + s.NewBatch(102).RecvMessage(client_message); + s.NewBatch(103).RecvCloseOnServer(client_close); // WARNING!! // It's believed the following line (and the associated batch) is the only // test we have for failing a receive operation in a batch. - cqv.Expect(grpc_core::CqVerifier::tag(102), false); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 1); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT(absl::StartsWith(grpc_core::StringViewFromSlice(details), - "Received message larger than max")); - grpc_slice_unref(details); - grpc_slice_unref(request_payload_slice); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(recv_payload); - grpc_call_unref(c); - if (s != nullptr) grpc_call_unref(s); + Expect(102, false); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_TRUE(client_close.was_cancelled()); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_THAT(server_status.message(), + StartsWith("Received message larger than max")); } -// Test receive message limit with compressed response larger than the limit. -static void test_max_receive_message_length_on_compressed_response( - const CoreTestConfiguration& config) { - gpr_log(GPR_INFO, - "testing max receive message length on compressed response"); - - grpc_call* c = nullptr; - grpc_call* s = nullptr; - grpc_op ops[6]; - grpc_op* op; - grpc_slice response_payload_slice = grpc_slice_malloc(1024); - memset(GRPC_SLICE_START_PTR(response_payload_slice), 'a', 1024); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* recv_payload = nullptr; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - +TEST_P(Http2Test, MaxMessageLengthOnClientOnResponseWithCompression) { + SKIP_IF_MINSTACK(); // Set limit via channel args. - grpc_arg arg[1]; - arg[0] = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH), 5); - grpc_channel_args* client_args = - grpc_channel_args_copy_and_add(nullptr, arg, 1); - - auto f = begin_test(config, "test_max_response_message_length", client_args, - nullptr); - { - grpc_core::ExecCtx exec_ctx; - grpc_channel_args_destroy(client_args); - } - grpc_core::CqVerifier cqv(f->cq()); - - c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, - gpr_inf_future(GPR_CLOCK_REALTIME), nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &recv_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - grpc_metadata compression_md = gzip_compression_override(); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &compression_md; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED); - GPR_ASSERT(absl::StartsWith(grpc_core::StringViewFromSlice(details), - "Received message larger than max")); - grpc_slice_unref(details); - grpc_slice_unref(response_payload_slice); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(recv_payload); - - grpc_call_unref(c); - if (s != nullptr) grpc_call_unref(s); -} - -void max_message_length(const CoreTestConfiguration& config) { - test_max_message_length_on_request(config, false /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, true /* send_limit */, - false /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - true /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_request(config, true /* send_limit */, - true /* use_service_config */, - true /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - true /* use_service_config */, - false /* use_string_json_value */); - test_max_message_length_on_response(config, false /* send_limit */, - true /* use_service_config */, - true /* use_string_json_value */); - // The following tests are not useful for inproc transport and do not work - // with our simple proxy. - if (strcmp(config.name, "inproc") != 0 && - (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) == 0) { - test_max_receive_message_length_on_compressed_request(config); - test_max_receive_message_length_on_compressed_response(config); - } + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, 5)); + auto c = NewClientCall("/service/method").Create(); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({{"grpc-internal-encoding-request", "gzip"}}) + .RecvCloseOnServer(client_close) + .SendMessage(std::string(1024, 'a')) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_EQ(server_status.status(), GRPC_STATUS_RESOURCE_EXHAUSTED); + EXPECT_THAT(server_status.message(), + StartsWith("Received message larger than max")); } -void max_message_length_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/negative_deadline.cc b/test/core/end2end/tests/negative_deadline.cc index 1c0935ec9a2..e46cbd24a1f 100644 --- a/test/core/end2end/tests/negative_deadline.cc +++ b/test/core/end2end/tests/negative_deadline.cc @@ -16,109 +16,30 @@ // // -#include -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f, size_t num_ops) { - grpc_call* c; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops); - - gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - GPR_ASSERT(num_ops <= (size_t)(op - ops)); - error = grpc_call_start_batch(c, ops, num_ops, grpc_core::CqVerifier::tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - - grpc_call_unref(c); -} - -static void test_invoke_simple_request(const CoreTestConfiguration& config, - size_t num_ops) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - simple_request_body(config, f.get(), num_ops); -} - -void negative_deadline(const CoreTestConfiguration& config) { - size_t i; - for (i = 1; i <= 4; i++) { - test_invoke_simple_request(config, i); - } +namespace grpc_core { +namespace { + +TEST_P(CoreDeadlineTest, NegativeDeadline) { + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(-1)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .RecvStatusOnClient(server_status) + .RecvInitialMetadata(server_initial_metadata) + .SendInitialMetadata({}) + .SendCloseFromClient(); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_DEADLINE_EXCEEDED); } -void negative_deadline_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/no_logging.cc b/test/core/end2end/tests/no_logging.cc index 6cde13c039d..9efc6a6edb4 100644 --- a/test/core/end2end/tests/no_logging.cc +++ b/test/core/end2end/tests/no_logging.cc @@ -16,234 +16,113 @@ // // -#include -#include - -#include -#include +#include #include #include "absl/strings/str_cat.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/env.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -enum { TIMEOUT = 200000 }; void gpr_default_log(gpr_log_func_args* args); -static void test_no_log(gpr_log_func_args* args) { - std::string message = absl::StrCat("Unwanted log: ", args->message); - args->message = message.c_str(); - gpr_default_log(args); - abort(); -} - -static void test_no_error_log(gpr_log_func_args* args) { - if (args->severity == GPR_LOG_SEVERITY_ERROR) { - test_no_log(args); +namespace grpc_core { + +class Verifier { + public: + Verifier() { + if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + saved_severity_ = GPR_LOG_SEVERITY_DEBUG; + } else if (gpr_should_log(GPR_LOG_SEVERITY_INFO)) { + saved_severity_ = GPR_LOG_SEVERITY_INFO; + } else if (gpr_should_log(GPR_LOG_SEVERITY_ERROR)) { + saved_severity_ = GPR_LOG_SEVERITY_ERROR; + } else { + saved_severity_ = + static_cast(GPR_LOG_SEVERITY_ERROR + 1); + } + grpc_tracer_set_enabled("all", 0); + gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); + gpr_set_log_function(DispatchLog); } -} - -static gpr_atm g_log_func = reinterpret_cast(gpr_default_log); - -static void log_dispatcher_func(gpr_log_func_args* args) { - gpr_log_func log_func = - reinterpret_cast(gpr_atm_no_barrier_load(&g_log_func)); - log_func(args); -} - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} + ~Verifier() { + gpr_set_log_function(gpr_default_log); + saved_trace_flags_.Restore(); + gpr_set_log_verbosity(saved_severity_); + } + Verifier(const Verifier&) = delete; + Verifier& operator=(const Verifier&) = delete; -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} + void FailOnAnyLog() { g_log_func_.store(NoLog); } + void FailOnNonErrorLog() { g_log_func_.store(NoErrorLog); } -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = - begin_test(config, "test_invoke_simple_request_with_no_error_logging", - nullptr, nullptr); - simple_request_body(config, f.get()); -} + private: + static void DispatchLog(gpr_log_func_args* args) { g_log_func_.load()(args); } -static void test_invoke_10_simple_requests( - const CoreTestConfiguration& config) { - int i; - auto f = - begin_test(config, "test_invoke_10_simple_requests_with_no_error_logging", - nullptr, nullptr); - for (i = 0; i < 10; i++) { - simple_request_body(config, f.get()); - gpr_log(GPR_INFO, "Passed simple request %d", i); + static void NoLog(gpr_log_func_args* args) { + std::string message = absl::StrCat("Unwanted log: ", args->message); + args->message = message.c_str(); + gpr_default_log(args); + GTEST_FAIL(); } - simple_request_body(config, f.get()); -} -static void test_no_error_logging_in_entire_process( - const CoreTestConfiguration& config) { - int i; - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_error_log); - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); + static void NoErrorLog(gpr_log_func_args* args) { + if (args->severity == GPR_LOG_SEVERITY_ERROR) { + NoLog(args); + } } - test_invoke_10_simple_requests(config); - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); -} -static void test_no_logging_in_one_request( - const CoreTestConfiguration& config) { - int i; - auto f = - begin_test(config, "test_no_logging_in_last_request", nullptr, nullptr); - for (i = 0; i < 10; i++) { - simple_request_body(config, f.get()); - } - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)test_no_log); - simple_request_body(config, f.get()); - gpr_atm_no_barrier_store(&g_log_func, (gpr_atm)gpr_default_log); + gpr_log_severity saved_severity_; + SavedTraceFlags saved_trace_flags_; + static std::atomic g_log_func_; +}; + +std::atomic Verifier::g_log_func_(gpr_default_log); + +void SimpleRequest(CoreEnd2endTest& test) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + EXPECT_NE(s.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -void no_logging(const CoreTestConfiguration& config) { - grpc_core::SetEnv("GRPC_TRACE", ""); - gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); - grpc_tracer_set_enabled("all", 0); - gpr_set_log_function(log_dispatcher_func); - test_no_logging_in_one_request(config); - test_no_error_logging_in_entire_process(config); - gpr_set_log_function(gpr_default_log); +TEST_P(NoLoggingTest, NoLoggingTest) { + Verifier verifier; + verifier.FailOnNonErrorLog(); + for (int i = 0; i < 10; i++) { + SimpleRequest(*this); + } + verifier.FailOnAnyLog(); + SimpleRequest(*this); } -void no_logging_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/no_op.cc b/test/core/end2end/tests/no_op.cc index 66c20748347..21e0255b38f 100644 --- a/test/core/end2end/tests/no_op.cc +++ b/test/core/end2end/tests/no_op.cc @@ -16,30 +16,10 @@ // // -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include "src/core/lib/channel/channel_args.h" #include "test/core/end2end/end2end_tests.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void test_no_op(const CoreTestConfiguration& config) { - auto f = begin_test(config, "no-op", nullptr, nullptr); -} - -void no_op(const CoreTestConfiguration& config) { test_no_op(config); } - -void no_op_pre_init(void) {} +namespace grpc_core { +TEST_P(CoreEnd2endTest, NoOp) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/payload.cc b/test/core/end2end/tests/payload.cc index a4b3cfd498e..6c9dc350507 100644 --- a/test/core/end2end/tests/payload.cc +++ b/test/core/end2end/tests/payload.cc @@ -16,230 +16,74 @@ // // -#include -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -// Creates and returns a grpc_slice containing random alphanumeric characters. -// -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char* output; - const size_t output_size = 1024 * 1024; - output = static_cast(gpr_malloc(output_size)); - for (i = 0; i < output_size - 1; ++i) { - output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; - } - output[output_size - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; -} +namespace grpc_core { -static void request_response_with_payload( - const CoreTestConfiguration& /*config*/, CoreTestFixture* f) { +namespace { +void RequestResponseWithPayload(CoreEnd2endTest& test) { // Create large request and response bodies. These are big enough to require // multiple round trips to deliver to the peer, and their exact contents of // will be verified on completion. - grpc_slice request_payload_slice = generate_random_slice(); - grpc_slice response_payload_slice = generate_random_slice(); - - grpc_call* c; - grpc_call* s; - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(60); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); + auto request_slice = RandomSlice(1024 * 1024); + auto response_slice = RandomSlice(1024 * 1024); + + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(60)).Create(); + + CoreEnd2endTest::IncomingMetadata server_initial_md; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage(request_slice.Ref()) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_md) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + + CoreEnd2endTest::IncomingCall s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage(response_slice.Ref()) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + test.Expect(103, true); + test.Expect(1, true); + test.Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), request_slice); + EXPECT_EQ(server_message.payload(), response_slice); } +} // namespace // Client sends a request with payload, server reads then returns a response // payload and status. -static void test_invoke_request_response_with_payload( - const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_request_response_with_payload", - nullptr, nullptr); - request_response_with_payload(config, f.get()); +TEST_P(CoreLargeSendTest, RequestResponseWithPayload) { + RequestResponseWithPayload(*this); } -static void test_invoke_10_request_response_with_payload( - const CoreTestConfiguration& config) { - int i; - auto f = begin_test(config, "test_invoke_10_request_response_with_payload", - nullptr, nullptr); - for (i = 0; i < 10; i++) { - request_response_with_payload(config, f.get()); +TEST_P(CoreLargeSendTest, RequestResponseWithPayload10Times) { + for (int i = 0; i < 10; i++) { + RequestResponseWithPayload(*this); } } -void payload(const CoreTestConfiguration& config) { - test_invoke_request_response_with_payload(config); - test_invoke_10_request_response_with_payload(config); -} - -void payload_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/ping.cc b/test/core/end2end/tests/ping.cc index 83abe51648a..e34b624180a 100644 --- a/test/core/end2end/tests/ping.cc +++ b/test/core/end2end/tests/ping.cc @@ -16,81 +16,52 @@ // // -#include -#include +#include "gmock/gmock.h" +#include "gtest/gtest.h" #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/surface/channel.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -#define PING_NUM 5 +namespace grpc_core { +namespace { -static void test_ping(const CoreTestConfiguration& config, - int min_time_between_pings_ms) { - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - grpc_core::CqVerifier cqv(f->cq()); +TEST_P(RetryHttp2Test, Ping) { + const int kPingCount = 5; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; - int i; - - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0) - .Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); - auto server_args = - grpc_core::ChannelArgs() - .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 0) - .Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1); - - f->InitClient(client_args); - f->InitServer(server_args); - - grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(0), - nullptr); - cqv.Expect(grpc_core::CqVerifier::tag(0), false); - + InitClient(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, 0) + .Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1)); + InitServer(ChannelArgs() + .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 0) + .Set(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1)); + PingServerFromClient(0); + Expect(0, false); + Step(); // check that we're still in idle, and start connecting - GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 1) == - GRPC_CHANNEL_IDLE); + EXPECT_EQ(CheckConnectivityState(true), GRPC_CHANNEL_IDLE); // we'll go through some set of transitions (some might be missed), until // READY is reached while (state != GRPC_CHANNEL_READY) { - grpc_channel_watch_connectivity_state( - f->client(), state, - gpr_time_add(grpc_timeout_seconds_to_deadline(3), - gpr_time_from_millis(min_time_between_pings_ms * PING_NUM, - GPR_TIMESPAN)), - f->cq(), grpc_core::CqVerifier::tag(99)); - cqv.Expect(grpc_core::CqVerifier::tag(99), true); - cqv.Verify(); - state = grpc_channel_check_connectivity_state(f->client(), 0); - GPR_ASSERT(state == GRPC_CHANNEL_READY || - state == GRPC_CHANNEL_CONNECTING || - state == GRPC_CHANNEL_TRANSIENT_FAILURE); + WatchConnectivityState(state, Duration::Seconds(3), 99); + Expect(99, true); + Step(); + state = CheckConnectivityState(false); + EXPECT_THAT(state, + ::testing::AnyOf(GRPC_CHANNEL_READY, GRPC_CHANNEL_CONNECTING, + GRPC_CHANNEL_TRANSIENT_FAILURE)); } - - for (i = 1; i <= PING_NUM; i++) { - grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(i), - nullptr); - cqv.Expect(grpc_core::CqVerifier::tag(i), true); - cqv.Verify(); + for (int i = 1; i <= kPingCount; i++) { + PingServerFromClient(i); + Expect(i, true); + Step(); } - - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(0xdead)); - cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true); - cqv.Verify(); -} - -void ping(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_ping(config, 0); - test_ping(config, 100); + ShutdownServerAndNotify(1000); + Expect(1000, true); + Step(); } -void ping_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/ping_pong_streaming.cc b/test/core/end2end/tests/ping_pong_streaming.cc index 394da3aae04..dbbb4de1d1e 100644 --- a/test/core/end2end/tests/ping_pong_streaming.cc +++ b/test/core/end2end/tests/ping_pong_streaming.cc @@ -16,221 +16,57 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { // Client pings and server pongs. Repeat messages rounds before finishing. -static void test_pingpong_streaming(const CoreTestConfiguration& config, - int messages) { - auto f = begin_test(config, "test_pingpong_streaming", nullptr, nullptr); - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_byte_buffer* request_payload; - grpc_byte_buffer* request_payload_recv; - grpc_byte_buffer* response_payload; - grpc_byte_buffer* response_payload_recv; - int i; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(100), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(101), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - for (i = 0; i < messages; i++) { - request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); +void PingPongStreaming(CoreEnd2endTest& test, int num_messages) { + auto request_slice = RandomSlice(20); + auto response_slice = RandomSlice(15); + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_md; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_md) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(100); + test.Expect(100, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close); + for (int i = 0; i < num_messages; i++) { + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(2).SendMessage(request_slice.Ref()).RecvMessage(server_message); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + test.Expect(102, true); + test.Step(); + s.NewBatch(103).SendMessage(response_slice.Ref()); + test.Expect(2, true); + test.Expect(103, true); + test.Step(); } - - grpc_slice_unref(request_payload_slice); - grpc_slice_unref(response_payload_slice); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_slice_unref(details); + c.NewBatch(3).SendCloseFromClient(); + s.NewBatch(104).SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}); + test.Expect(1, true); + test.Expect(3, true); + test.Expect(101, true); + test.Expect(104, true); + test.Step(); } -void ping_pong_streaming(const CoreTestConfiguration& config) { - int i; +TEST_P(CoreEnd2endTest, PingPongStreaming1) { PingPongStreaming(*this, 1); } - for (i = 1; i < 10; i++) { - test_pingpong_streaming(config, i); - } -} +TEST_P(CoreEnd2endTest, PingPongStreaming3) { PingPongStreaming(*this, 3); } + +TEST_P(CoreEnd2endTest, PingPongStreaming10) { PingPongStreaming(*this, 10); } -void ping_pong_streaming_pre_init(void) {} +TEST_P(CoreEnd2endTest, PingPongStreaming30) { PingPongStreaming(*this, 30); } +} // namespace grpc_core diff --git a/test/core/end2end/tests/proxy_auth.cc b/test/core/end2end/tests/proxy_auth.cc index 2ce8e0c2e8e..354088aa8ec 100644 --- a/test/core/end2end/tests/proxy_auth.cc +++ b/test/core/end2end/tests/proxy_auth.cc @@ -16,168 +16,51 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/fixtures/http_proxy_fixture.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); +namespace grpc_core { +namespace { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -static void test_invoke_proxy_auth(const CoreTestConfiguration& config) { +TEST_P(ProxyAuthTest, InvokeProxyAuth) { // Indicate that the proxy requires user auth - grpc_arg client_arg; - client_arg.type = GRPC_ARG_STRING; - client_arg.key = const_cast(GRPC_ARG_HTTP_PROXY_AUTH_CREDS); - client_arg.value.string = const_cast(GRPC_TEST_HTTP_PROXY_AUTH_CREDS); - grpc_channel_args client_args = {1, &client_arg}; - auto f = begin_test(config, "test_invoke_proxy_auth", &client_args, nullptr); - simple_request_body(config, f.get()); -} - -void proxy_auth(const CoreTestConfiguration& config) { - test_invoke_proxy_auth(config); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set(GRPC_ARG_HTTP_PROXY_AUTH_CREDS, + GRPC_TEST_HTTP_PROXY_AUTH_CREDS)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -void proxy_auth_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/registered_call.cc b/test/core/end2end/tests/registered_call.cc index 6d0b4c83559..45336728ba0 100644 --- a/test/core/end2end/tests/registered_call.cc +++ b/test/core/end2end/tests/registered_call.cc @@ -16,161 +16,53 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f, void* rc) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_registered_call(f->client(), nullptr, - GRPC_PROPAGATE_DEFAULTS, f->cq(), rc, - deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); +namespace grpc_core { +namespace { + +void SimpleRequestBody(CoreEnd2endTest& test, + CoreEnd2endTest::RegisteredCall rc) { + auto c = test.NewClientCall(rc).Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - void* rc = grpc_channel_register_call(f->client(), "/foo", nullptr, nullptr); - - simple_request_body(config, f.get(), rc); +TEST_P(CoreEnd2endTest, InvokeRegisteredCall) { + SimpleRequestBody(*this, RegisterCallOnClient("/foo", nullptr)); } -static void test_invoke_10_simple_requests( - const CoreTestConfiguration& config) { - int i; - auto f = - begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); - void* rc = grpc_channel_register_call(f->client(), "/foo", nullptr, nullptr); - - for (i = 0; i < 10; i++) { - simple_request_body(config, f.get(), rc); - gpr_log(GPR_INFO, "Passed simple request %d", i); +TEST_P(CoreEnd2endTest, Invoke10RegisteredCalls) { + auto rc = RegisterCallOnClient("/foo", nullptr); + for (int i = 0; i < 10; i++) { + SimpleRequestBody(*this, rc); } } -void registered_call(const CoreTestConfiguration& config) { - test_invoke_simple_request(config); - test_invoke_10_simple_requests(config); -} - -void registered_call_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/request_with_flags.cc b/test/core/end2end/tests/request_with_flags.cc index 408307fba98..5798d97d60f 100644 --- a/test/core/end2end/tests/request_with_flags.cc +++ b/test/core/end2end/tests/request_with_flags.cc @@ -19,167 +19,152 @@ #include #include -#include -#include -#include +#include +#include -#include "absl/strings/str_cat.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" #include #include -#include #include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/transport/transport.h" #include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -static gpr_timespec one_second_from_now(void) { - return grpc_timeout_seconds_to_deadline(1); -} +namespace grpc_core { +namespace { -static void test_invoke_request_with_flags( - const CoreTestConfiguration& config, uint32_t* flags_for_op, - grpc_call_error call_start_batch_expected_result) { - grpc_call* c; +void InvokeRequestWithFlags(CoreEnd2endTest& test, + std::map flags_for_op, + grpc_call_error call_start_batch_expected_result) { grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer* request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = begin_test( - config, - absl::StrCat("test_invoke_request_with_flags[", - absl::Hex(flags_for_op[GRPC_OP_SEND_INITIAL_METADATA]), ",", - absl::Hex(flags_for_op[GRPC_OP_SEND_MESSAGE]), ",", - absl::Hex(flags_for_op[GRPC_OP_SEND_CLOSE_FROM_CLIENT]), ",", - absl::Hex(flags_for_op[GRPC_OP_RECV_INITIAL_METADATA]), ",", - absl::Hex(flags_for_op[GRPC_OP_RECV_STATUS_ON_CLIENT]), - "]=>", - grpc_call_error_to_string(call_start_batch_expected_result)) - .c_str(), - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); grpc_op ops[6]; grpc_op* op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; - grpc_call_error expectation; - gpr_timespec deadline = one_second_from_now(); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); + auto get_flags = [flags_for_op](grpc_op_type op_type) -> uint32_t { + auto it = flags_for_op.find(op_type); + if (it == flags_for_op.end()) return 0; + return it->second; + }; grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); + absl::optional c = + test.NewClientCall("/foo").Timeout(Duration::Seconds(1)).Create(); + memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; - op->flags = flags_for_op[op->op]; + op->flags = get_flags(op->op); op->reserved = nullptr; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; - op->flags = flags_for_op[op->op]; + op->flags = get_flags(op->op); op->reserved = nullptr; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = flags_for_op[op->op]; + op->flags = get_flags(op->op); op->reserved = nullptr; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = flags_for_op[op->op]; + op->flags = get_flags(op->op); op->reserved = nullptr; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; - op->flags = flags_for_op[op->op]; + op->flags = get_flags(op->op); op->reserved = nullptr; op++; - expectation = call_start_batch_expected_result; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(expectation == error); - - if (expectation == GRPC_CALL_OK) { - if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES) { - GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, nullptr)); + error = grpc_call_start_batch(c->c_call(), ops, static_cast(op - ops), + CqVerifier::tag(1), nullptr); + EXPECT_EQ(error, call_start_batch_expected_result); + if (error == GRPC_CALL_OK) { + if (test.GetParam()->feature_mask & FEATURE_MASK_IS_MINSTACK) { + c->Cancel(); } - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); + test.Expect(1, true); + test.Step(); grpc_slice_unref(details); } + c.reset(); + grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); + grpc_byte_buffer_destroy(request_payload); +} - grpc_call_unref(c); +TEST_P(CoreEnd2endTest, BadFlagsOnSendInitialMetadata) { + InvokeRequestWithFlags(*this, {{GRPC_OP_SEND_INITIAL_METADATA, 0xdeadbeef}}, + GRPC_CALL_ERROR_INVALID_FLAGS); +} - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); +TEST_P(CoreEnd2endTest, BadFlagsOnSendMessage) { + InvokeRequestWithFlags(*this, {{GRPC_OP_SEND_MESSAGE, 0xdeadbeef}}, + GRPC_CALL_ERROR_INVALID_FLAGS); } -void request_with_flags(const CoreTestConfiguration& config) { - size_t i; - uint32_t flags_for_op[GRPC_OP_RECV_CLOSE_ON_SERVER + 1]; - - { - // check that all grpc_op_types fail when their flag value is set to an - // invalid value - int indices[] = {GRPC_OP_SEND_INITIAL_METADATA, GRPC_OP_SEND_MESSAGE, - GRPC_OP_SEND_CLOSE_FROM_CLIENT, - GRPC_OP_RECV_INITIAL_METADATA, - GRPC_OP_RECV_STATUS_ON_CLIENT}; - for (i = 0; i < GPR_ARRAY_SIZE(indices); ++i) { - memset(flags_for_op, 0, sizeof(flags_for_op)); - flags_for_op[indices[i]] = 0xDEADBEEF; - test_invoke_request_with_flags(config, flags_for_op, - GRPC_CALL_ERROR_INVALID_FLAGS); - } - } - { - // check valid operation with allowed flags for GRPC_OP_SEND_BUFFER - uint32_t flags[] = {GRPC_WRITE_BUFFER_HINT, GRPC_WRITE_NO_COMPRESS, - GRPC_WRITE_INTERNAL_COMPRESS}; - for (i = 0; i < GPR_ARRAY_SIZE(flags); ++i) { - memset(flags_for_op, 0, sizeof(flags_for_op)); - flags_for_op[GRPC_OP_SEND_MESSAGE] = flags[i]; - test_invoke_request_with_flags(config, flags_for_op, GRPC_CALL_OK); - } - } +TEST_P(CoreEnd2endTest, BadFlagsOnSendCloseFromClient) { + InvokeRequestWithFlags(*this, {{GRPC_OP_SEND_CLOSE_FROM_CLIENT, 0xdeadbeef}}, + GRPC_CALL_ERROR_INVALID_FLAGS); +} + +TEST_P(CoreEnd2endTest, BadFlagsOnRecvInitialMetadata) { + InvokeRequestWithFlags(*this, {{GRPC_OP_RECV_INITIAL_METADATA, 0xdeadbeef}}, + GRPC_CALL_ERROR_INVALID_FLAGS); +} + +TEST_P(CoreEnd2endTest, BadFlagsOnRecvStatusOnClient) { + InvokeRequestWithFlags(*this, {{GRPC_OP_RECV_STATUS_ON_CLIENT, 0xdeadbeef}}, + GRPC_CALL_ERROR_INVALID_FLAGS); +} + +TEST_P(CoreEnd2endTest, WriteBufferIntAcceptedOnSendMessage) { + InvokeRequestWithFlags( + *this, {{GRPC_OP_SEND_MESSAGE, GRPC_WRITE_BUFFER_HINT}}, GRPC_CALL_OK); +} + +TEST_P(CoreEnd2endTest, WriteNoCompressAcceptedOnSendMessage) { + InvokeRequestWithFlags( + *this, {{GRPC_OP_SEND_MESSAGE, GRPC_WRITE_NO_COMPRESS}}, GRPC_CALL_OK); +} + +TEST_P(CoreEnd2endTest, WriteBufferHintAndNoCompressAcceptedOnSendMessage) { + InvokeRequestWithFlags( + *this, + {{GRPC_OP_SEND_MESSAGE, GRPC_WRITE_BUFFER_HINT | GRPC_WRITE_NO_COMPRESS}}, + GRPC_CALL_OK); +} + +TEST_P(CoreEnd2endTest, WriteInternalCompressAcceptedOnSendMessage) { + InvokeRequestWithFlags(*this, + {{GRPC_OP_SEND_MESSAGE, GRPC_WRITE_INTERNAL_COMPRESS}}, + GRPC_CALL_OK); } -void request_with_flags_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/request_with_payload.cc b/test/core/end2end/tests/request_with_payload.cc index 9c74ab19e99..0b1c2c1ee44 100644 --- a/test/core/end2end/tests/request_with_payload.cc +++ b/test/core/end2end/tests/request_with_payload.cc @@ -16,172 +16,46 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Client sends a request with payload, server reads then returns status. -static void test_invoke_request_with_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = - begin_test(config, "test_invoke_request_with_payload", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); -} -void request_with_payload(const CoreTestConfiguration& config) { - test_invoke_request_with_payload(config); +namespace grpc_core { +namespace { + +TEST_P(CoreEnd2endTest, RequestWithPayload) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + IncomingMessage client_message; + s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message); + Expect(102, true); + Step(); + IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "hello world"); } -void request_with_payload_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/resource_quota_server.cc b/test/core/end2end/tests/resource_quota_server.cc index d4092f79482..fa642ed71ca 100644 --- a/test/core/end2end/tests/resource_quota_server.cc +++ b/test/core/end2end/tests/resource_quota_server.cc @@ -16,329 +16,123 @@ // // -#include -#include -#include -#include - -#include +#include #include -#include +#include #include "absl/strings/str_format.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include #include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/crash.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" +#include "src/core/lib/slice/slice.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} -// Creates and returns a grpc_slice containing random alphanumeric characters. -// -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char* output; - const size_t output_size = 1024 * 1024; - output = static_cast(gpr_malloc(output_size)); - for (i = 0; i < output_size - 1; ++i) { - output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; +namespace grpc_core { +namespace { + +const int kNumCalls = 8; +const int kClientBaseTag = 1000; +const int kServerStartBaseTag = 2000; +const int kServerRecvBaseTag = 3000; +const int kServerEndBaseTag = 4000; + +template +auto MakeVec(F init) { + std::vector v; + v.reserve(kNumCalls); + for (int i = 0; i < kNumCalls; ++i) { + v.push_back(init(i)); } - output[output_size - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; + return v; } -void resource_quota_server(const CoreTestConfiguration& config) { +TEST_P(ResourceQuotaTest, ResourceQuota) { grpc_resource_quota* resource_quota = grpc_resource_quota_create("test_server"); - grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024); - -#define NUM_CALLS 100 -#define CLIENT_BASE_TAG 0x1000 -#define SERVER_START_BASE_TAG 0x2000 -#define SERVER_RECV_BASE_TAG 0x3000 -#define SERVER_END_BASE_TAG 0x4000 - - grpc_arg arg; - arg.key = const_cast(GRPC_ARG_RESOURCE_QUOTA); - arg.type = GRPC_ARG_POINTER; - arg.value.pointer.p = resource_quota; - arg.value.pointer.vtable = grpc_resource_quota_arg_vtable(); - grpc_channel_args args = {1, &arg}; - - auto f = begin_test(config, "resource_quota_server", nullptr, &args); - + grpc_resource_quota_resize(resource_quota, 1024 * 1024); + InitServer(ChannelArgs().Set( + GRPC_ARG_RESOURCE_QUOTA, + ChannelArgs::Pointer(resource_quota, grpc_resource_quota_arg_vtable()))); + InitClient(ChannelArgs()); // Create large request and response bodies. These are big enough to require // multiple round trips to deliver to the peer, and their exact contents of // will be verified on completion. - grpc_slice request_payload_slice = generate_random_slice(); + auto requests = MakeVec([](int) { return RandomSlice(128 * 1024); }); + auto server_calls = + MakeVec([this](int i) { return RequestCall(kServerRecvBaseTag + i); }); + std::vector server_metadata(kNumCalls); + std::vector server_status(kNumCalls); + std::vector client_message(kNumCalls); + std::vector client_close(kNumCalls); + auto client_calls = + MakeVec([this, &requests, &server_metadata, &server_status](int i) { + auto c = NewClientCall("/foo").Timeout(Duration::Minutes(1)).Create(); + c.NewBatch(kClientBaseTag + i) + .SendInitialMetadata({}, GRPC_INITIAL_METADATA_WAIT_FOR_READY) + .SendMessage(requests[i].Ref()) + .SendCloseFromClient() + .RecvInitialMetadata(server_metadata[i]) + .RecvStatusOnClient(server_status[i]); + return c; + }); + for (int i = 0; i < kNumCalls; i++) { + Expect(kClientBaseTag + i, true); + Expect(kServerRecvBaseTag + i, + PerformAction{[&server_calls, &client_message, i](bool success) { + EXPECT_TRUE(success); + server_calls[i] + .NewBatch(kServerStartBaseTag + i) + .RecvMessage(client_message[i]) + .SendInitialMetadata({}); + }}); + Expect(kServerStartBaseTag + i, + PerformAction{[&server_calls, &client_close, i](bool) { + server_calls[i] + .NewBatch(kServerEndBaseTag + i) + .RecvCloseOnServer(client_close[i]) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + }}); + Expect(kServerEndBaseTag + i, true); + } + Step(Duration::Seconds(30)); - grpc_call** client_calls = - static_cast(malloc(sizeof(grpc_call*) * NUM_CALLS)); - grpc_call** server_calls = - static_cast(malloc(sizeof(grpc_call*) * NUM_CALLS)); - grpc_metadata_array* initial_metadata_recv = - static_cast( - malloc(sizeof(grpc_metadata_array) * NUM_CALLS)); - grpc_metadata_array* trailing_metadata_recv = - static_cast( - malloc(sizeof(grpc_metadata_array) * NUM_CALLS)); - grpc_metadata_array* request_metadata_recv = - static_cast( - malloc(sizeof(grpc_metadata_array) * NUM_CALLS)); - grpc_call_details* call_details = static_cast( - malloc(sizeof(grpc_call_details) * NUM_CALLS)); - grpc_status_code* status = static_cast( - malloc(sizeof(grpc_status_code) * NUM_CALLS)); - grpc_slice* details = - static_cast(malloc(sizeof(grpc_slice) * NUM_CALLS)); - grpc_byte_buffer** request_payload = static_cast( - malloc(sizeof(grpc_byte_buffer*) * NUM_CALLS)); - grpc_byte_buffer** request_payload_recv = static_cast( - malloc(sizeof(grpc_byte_buffer*) * NUM_CALLS)); - int* was_cancelled = static_cast(malloc(sizeof(int) * NUM_CALLS)); - grpc_call_error error; - int pending_client_calls = 0; - int pending_server_start_calls = 0; - int pending_server_recv_calls = 0; - int pending_server_end_calls = 0; int cancelled_calls_on_client = 0; int cancelled_calls_on_server = 0; int deadline_exceeded = 0; int unavailable = 0; - - grpc_op ops[6]; - grpc_op* op; - - for (int i = 0; i < NUM_CALLS; i++) { - grpc_metadata_array_init(&initial_metadata_recv[i]); - grpc_metadata_array_init(&trailing_metadata_recv[i]); - grpc_metadata_array_init(&request_metadata_recv[i]); - grpc_call_details_init(&call_details[i]); - request_payload[i] = grpc_raw_byte_buffer_create(&request_payload_slice, 1); - request_payload_recv[i] = nullptr; - was_cancelled[i] = 0; - } - - for (int i = 0; i < NUM_CALLS; i++) { - error = grpc_server_request_call( - f->server(), &server_calls[i], &call_details[i], - &request_metadata_recv[i], f->cq(), f->cq(), - grpc_core::CqVerifier::tag(SERVER_START_BASE_TAG + i)); - GPR_ASSERT(GRPC_CALL_OK == error); - - pending_server_start_calls++; - } - - for (int i = 0; i < NUM_CALLS; i++) { - client_calls[i] = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/foo"), nullptr, - grpc_timeout_seconds_to_deadline(60), nullptr); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload[i]; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv[i]; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = - &trailing_metadata_recv[i]; - op->data.recv_status_on_client.status = &status[i]; - op->data.recv_status_on_client.status_details = &details[i]; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch( - client_calls[i], ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(CLIENT_BASE_TAG + i), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - pending_client_calls++; - } - - while (pending_client_calls + pending_server_recv_calls + - pending_server_end_calls > - 0) { - grpc_event ev = grpc_completion_queue_next( - f->cq(), grpc_timeout_seconds_to_deadline(60), nullptr); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - - int ev_tag = static_cast(reinterpret_cast(ev.tag)); - if (ev_tag < CLIENT_BASE_TAG) { - abort(); // illegal tag - } else if (ev_tag < SERVER_START_BASE_TAG) { - // client call finished - int call_id = ev_tag - CLIENT_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - switch (status[call_id]) { - case GRPC_STATUS_RESOURCE_EXHAUSTED: - cancelled_calls_on_client++; - break; - case GRPC_STATUS_DEADLINE_EXCEEDED: - deadline_exceeded++; - break; - case GRPC_STATUS_UNAVAILABLE: - unavailable++; - break; - case GRPC_STATUS_OK: - break; - default: - grpc_core::Crash( - absl::StrFormat("Unexpected status code: %d", status[call_id])); - } - GPR_ASSERT(pending_client_calls > 0); - - grpc_metadata_array_destroy(&initial_metadata_recv[call_id]); - grpc_metadata_array_destroy(&trailing_metadata_recv[call_id]); - grpc_call_unref(client_calls[call_id]); - grpc_slice_unref(details[call_id]); - grpc_byte_buffer_destroy(request_payload[call_id]); - - pending_client_calls--; - } else if (ev_tag < SERVER_RECV_BASE_TAG) { - // new incoming call to the server - int call_id = ev_tag - SERVER_START_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv[call_id]; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch( - server_calls[call_id], ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(SERVER_RECV_BASE_TAG + call_id), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(pending_server_start_calls > 0); - pending_server_start_calls--; - pending_server_recv_calls++; - - grpc_call_details_destroy(&call_details[call_id]); - grpc_metadata_array_destroy(&request_metadata_recv[call_id]); - } else if (ev_tag < SERVER_END_BASE_TAG) { - // finished read on the server - int call_id = ev_tag - SERVER_RECV_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - if (ev.success) { - if (request_payload_recv[call_id] != nullptr) { - grpc_byte_buffer_destroy(request_payload_recv[call_id]); - request_payload_recv[call_id] = nullptr; - } - } else { - GPR_ASSERT(request_payload_recv[call_id] == nullptr); - } - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled[call_id]; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch( - server_calls[call_id], ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(SERVER_END_BASE_TAG + call_id), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(pending_server_recv_calls > 0); - pending_server_recv_calls--; - pending_server_end_calls++; - } else { - int call_id = ev_tag - SERVER_END_BASE_TAG; - GPR_ASSERT(call_id >= 0); - GPR_ASSERT(call_id < NUM_CALLS); - - if (was_cancelled[call_id]) { - cancelled_calls_on_server++; - } - GPR_ASSERT(pending_server_end_calls > 0); - pending_server_end_calls--; - - grpc_call_unref(server_calls[call_id]); + for (int i = 0; i < kNumCalls; i++) { + switch (server_status[i].status()) { + case GRPC_STATUS_RESOURCE_EXHAUSTED: + cancelled_calls_on_client++; + break; + case GRPC_STATUS_DEADLINE_EXCEEDED: + deadline_exceeded++; + break; + case GRPC_STATUS_UNAVAILABLE: + unavailable++; + break; + case GRPC_STATUS_OK: + break; + default: + Crash(absl::StrFormat("Unexpected status code: %d", + server_status[i].status())); + } + if (client_close[i].was_cancelled()) { + cancelled_calls_on_server++; } } - gpr_log(GPR_INFO, "Done. %d total calls: %d cancelled at server, %d cancelled at " "client, %d timed out, %d unavailable.", - NUM_CALLS, cancelled_calls_on_server, cancelled_calls_on_client, + kNumCalls, cancelled_calls_on_server, cancelled_calls_on_client, deadline_exceeded, unavailable); - - f->ShutdownServer(); - - grpc_slice_unref(request_payload_slice); - grpc_resource_quota_unref(resource_quota); - - free(client_calls); - free(server_calls); - free(initial_metadata_recv); - free(trailing_metadata_recv); - free(request_metadata_recv); - free(call_details); - free(status); - free(details); - free(request_payload); - free(request_payload_recv); - free(was_cancelled); } -void resource_quota_server_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry.cc b/test/core/end2end/tests/retry.cc index 46d650ad38f..5e725ac3ab6 100644 --- a/test/core/end2end/tests/retry.cc +++ b/test/core/end2end/tests/retry.cc @@ -16,267 +16,100 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { // Tests a basic retry scenario: // - 2 retries allowed for ABORTED status // - first attempt returns ABORTED // - second attempt returns OK -static void test_retry(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); +TEST_P(RetryTest, Retry) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was not sent in the // initial attempt. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); + EXPECT_EQ(s.GetInitialMetadata("grpc-previous-rpc-attempts"), absl::nullopt); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); + auto s2 = RequestCall(201); + Expect(201, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - bool found_retry_header = false; - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - if (grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))) { - GPR_ASSERT(grpc_slice_eq(request_metadata_recv.metadata[i].value, - grpc_slice_from_static_string("1"))); - found_retry_header = true; - break; - } - } - GPR_ASSERT(found_retry_header); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(203), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(203), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry(config); + EXPECT_EQ(s2.GetInitialMetadata("grpc-previous-rpc-attempts"), "1"); + + EXPECT_NE(s2.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + + IncomingMessage server_message2; + s2.NewBatch(202) + .SendInitialMetadata({}) + .RecvMessage(server_message2) + .SendMessage("bar"); + IncomingCloseOnServer client_close2; + s2.NewBatch(203) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(203, true); + Expect(1, true); + Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close2.was_cancelled()); } -void retry_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc b/test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc index 52fbaf98433..c1372806f17 100644 --- a/test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc +++ b/test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc @@ -14,158 +14,65 @@ // limitations under the License. // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we can unref a call after the first attempt starts but // before any ops complete. This should not cause a memory leak. -static void test_retry_cancel_after_first_attempt_starts( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - // Make sure to dynamically allocate the request payload slice, so - // that the test will fail under ASAN if we don't clean up properly. - const char request_string[] = "foo"; - grpc_slice request_payload_slice = - grpc_slice_malloc_large(sizeof(request_string)); - memcpy(GRPC_SLICE_START_PTR(request_payload_slice), request_string, - sizeof(request_string)); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_slice_unref(request_payload_slice); - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_slice details; - grpc_call_error error; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_cancel_after_first_attempt_starts", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - +TEST_P(RetryTest, RetryCancelAfterFirstAttemptStarts) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + absl::optional c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); // Client starts send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c->NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); // Client starts recv_initial_metadata and recv_message, but not // recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c->NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); // Client starts recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingStatusOnClient server_status; + c->NewBatch(3).RecvStatusOnClient(server_status); // Client unrefs the call without starting recv_trailing_metadata. // This should trigger a cancellation. - grpc_call_unref(c); - + c.reset(); // The send ops batch and the first recv ops batch will fail in most // fixtures but will pass in the proxy fixtures on some platforms. - cqv.Expect(grpc_core::CqVerifier::tag(1), grpc_core::CqVerifier::AnyStatus()); - cqv.Expect(grpc_core::CqVerifier::tag(2), grpc_core::CqVerifier::AnyStatus()); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); -} - -void retry_cancel_after_first_attempt_starts( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_cancel_after_first_attempt_starts(config); + Expect(1, AnyStatus()); + Expect(2, AnyStatus()); + Expect(3, true); + Step(); } -void retry_cancel_after_first_attempt_starts_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_cancel_during_delay.cc b/test/core/end2end/tests/retry_cancel_during_delay.cc index 09e279c1018..b88a7e2e5c8 100644 --- a/test/core/end2end/tests/retry_cancel_during_delay.cc +++ b/test/core/end2end/tests/retry_cancel_during_delay.cc @@ -14,232 +14,104 @@ // limitations under the License. // -#include - -#include #include #include -#include -#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" -#include "absl/strings/string_view.h" -#include "absl/time/time.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/time_util.h" -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests retry cancellation during backoff. -static void test_retry_cancel_during_delay(const CoreTestConfiguration& config, - cancellation_mode mode) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - std::string service_config = absl::StrFormat( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"%ds\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}", - 10 * grpc_test_slowdown_factor()); - - grpc_arg args[] = { - grpc_channel_arg_string_create(const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast(service_config.c_str())), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - std::string name = absl::StrCat("retry_cancel_during_delay/", mode.name); - auto f = begin_test(config, name.c_str(), &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec expect_finish_before = grpc_timeout_seconds_to_deadline(10); - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +namespace grpc_core { +namespace { + +void TestRetryCancelDuringDelay( + CoreEnd2endTest& test, + std::unique_ptr cancellation_mode) { + test.InitServer(ChannelArgs()); + test.InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + absl::StrFormat( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"%ds\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}", + 10 * grpc_test_slowdown_factor()))); + auto expect_finish_before = + test.TimestampAfterDuration(Duration::Seconds(10)); + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client starts a batch with all 6 ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); // Server gets a call and fails with retryable status. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Step(); // Server should never get a second call, because the initial retry // delay is longer than the call's deadline. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - + auto s2 = test.RequestCall(201); // Initiate cancellation. - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - gpr_timespec finish_time = gpr_now(GPR_CLOCK_MONOTONIC); - - gpr_log(GPR_INFO, "status=%d expected=%d", status, mode.expect_status); - gpr_log(GPR_INFO, "message=\"%s\"", - std::string(grpc_core::StringViewFromSlice(details)).c_str()); - GPR_ASSERT(status == mode.expect_status); - GPR_ASSERT(was_cancelled == 0); - + cancellation_mode->Apply(c); + test.Expect(1, true); + test.Step(); + auto finish_time = Timestamp::Now(); + EXPECT_EQ(server_status.status(), cancellation_mode->ExpectedStatus()) + << server_status.message(); + EXPECT_FALSE(client_close.was_cancelled()); // Make sure we didn't wait the full deadline before failing. - gpr_log( - GPR_INFO, "Expect completion before: %s", - absl::FormatTime(grpc_core::ToAbslTime(expect_finish_before)).c_str()); - GPR_ASSERT(gpr_time_cmp(finish_time, expect_finish_before) < 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); + EXPECT_LT(finish_time, expect_finish_before); + // Shutdown the server to gc the requested call. + test.ShutdownServerAndNotify(1000); + test.Expect(1000, true); + test.Expect(201, false); + test.Step(); +} - grpc_call_unref(c); +TEST_P(RetryTest, CancelDuringDelay) { + TestRetryCancelDuringDelay(*this, std::make_unique()); } -void retry_cancel_during_delay(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) { - test_retry_cancel_during_delay(config, cancellation_modes[i]); - } +TEST_P(RetryTest, DeadlineDuringDelay) { + TestRetryCancelDuringDelay(*this, + std::make_unique()); } -void retry_cancel_during_delay_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc b/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc index bb48dab92e5..c61522adc70 100644 --- a/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc +++ b/test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc @@ -16,190 +16,92 @@ // // -#include - -#include #include #include #include -#include #include "absl/status/status.h" -#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests cancellation with multiple send op batches. -static void test_retry_cancel_with_multiple_send_batches( - const CoreTestConfiguration& config, cancellation_mode mode) { - grpc_call* c; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - char* peer; - - std::string service_config_string = absl::StrFormat( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"%ds\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}", - 5 * grpc_test_slowdown_factor()); - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_RETRIES), 1), - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast(service_config_string.c_str())), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - std::string name = - absl::StrCat("retry_cancel_with_multiple_send_batches/", mode.name); - auto f = begin_test(config, name.c_str(), &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(3); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - +void TestRetryCancelWithMultipleSendBatches( + CoreEnd2endTest& test, std::unique_ptr mode) { + test.InitServer(ChannelArgs()); + test.InitClient( + ChannelArgs() + .Set( + GRPC_ARG_SERVICE_CONFIG, + absl::StrFormat( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"%ds\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}", + 5 * grpc_test_slowdown_factor())) + // TODO(roth): do we need this now? + .Set(GRPC_ARG_ENABLE_RETRIES, true)); + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(3)) + .Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Start a batch containing send_initial_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(1).SendInitialMetadata({}); // Start a batch containing send_message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(2).SendMessage("foo"); // Start a batch containing send_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(3).SendCloseFromClient(); // Start a batch containing recv ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingMetadata server_incoming_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(4) + .RecvInitialMetadata(server_incoming_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); // Initiate cancellation. - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - + mode->Apply(c); // Client ops should now complete. - cqv.Expect(grpc_core::CqVerifier::tag(1), false); - cqv.Expect(grpc_core::CqVerifier::tag(2), false); - cqv.Expect(grpc_core::CqVerifier::tag(3), false); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - - gpr_log(GPR_INFO, "status=%d expected=%d", status, mode.expect_status); - GPR_ASSERT(status == mode.expect_status); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); + test.Expect(1, false); + test.Expect(2, false); + test.Expect(3, false); + test.Expect(4, true); + test.Step(); + EXPECT_EQ(server_status.status(), mode->ExpectedStatus()); } -namespace { - // A filter that fails all batches with send ops. class FailSendOpsFilter { public: @@ -230,7 +132,7 @@ class FailSendOpsFilter { batch, grpc_error_set_int( GRPC_ERROR_CREATE("FailSendOpsFilter failing batch"), - grpc_core::StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), + StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), calld->call_combiner_); return; } @@ -241,7 +143,7 @@ class FailSendOpsFilter { explicit CallData(const grpc_call_element_args* args) : call_combiner_(args->call_combiner) {} - grpc_core::CallCombiner* call_combiner_; + CallCombiner* call_combiner_; }; static grpc_error_handle Init(grpc_channel_element* elem, @@ -272,7 +174,7 @@ grpc_channel_filter FailSendOpsFilter::kFilterVtable = { "FailSendOpsFilter", }; -bool MaybeAddFilter(grpc_core::ChannelStackBuilder* builder) { +bool MaybeAddFilter(ChannelStackBuilder* builder) { // Skip on proxy (which explicitly disables retries). if (!builder->channel_args() .GetBool(GRPC_ARG_ENABLE_RETRIES) @@ -284,23 +186,24 @@ bool MaybeAddFilter(grpc_core::ChannelStackBuilder* builder) { return true; } -} // namespace +void RegisterFilter() { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0, + MaybeAddFilter); + }); +} -void retry_cancel_with_multiple_send_batches( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0, - MaybeAddFilter); - }, - [&config]() { - for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) { - test_retry_cancel_with_multiple_send_batches(config, - cancellation_modes[i]); - } - }); +TEST_P(RetryTest, RetryCancelWithMultipleSendBatches) { + RegisterFilter(); + TestRetryCancelWithMultipleSendBatches( + *this, std::make_unique()); } -void retry_cancel_with_multiple_send_batches_pre_init(void) {} +TEST_P(RetryTest, RetryDeadlineWithMultipleSendBatches) { + RegisterFilter(); + TestRetryCancelWithMultipleSendBatches( + *this, std::make_unique()); +} + +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_cancellation.cc b/test/core/end2end/tests/retry_cancellation.cc index e91c9e8887a..60759ed887b 100644 --- a/test/core/end2end/tests/retry_cancellation.cc +++ b/test/core/end2end/tests/retry_cancellation.cc @@ -16,215 +16,91 @@ // // -#include - -#include #include -#include -#include "absl/strings/str_cat.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/tests/cancel_test_helpers.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests retry cancellation. -static void test_retry_cancellation(const CoreTestConfiguration& config, - cancellation_mode mode) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 5,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " },\n" - " \"timeout\": \"10s\"\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - std::string name = absl::StrCat("retry_cancellation/", mode.name); - auto f = begin_test(config, name.c_str(), &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +void TestRetryCancellation(CoreEnd2endTest& test, + std::unique_ptr mode) { + test.InitServer(ChannelArgs()); + test.InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 5,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " },\n" + " \"timeout\": \"10s\"\n" + " } ]\n" + "}")); + auto c = test.NewClientCall("/service/method") + .Timeout(Duration::Seconds(5)) + .Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client starts a batch with all 6 ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); // Server gets a call and fails with retryable status. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + absl::optional s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s->NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Step(); + s.reset(); // Server gets a second call (the retry). - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - + s.emplace(test.RequestCall(201)); + test.Expect(201, true); + test.Step(); // Initiate cancellation. - GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == mode.expect_status); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); + mode->Apply(c); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), mode->ExpectedStatus()); + EXPECT_FALSE(client_close.was_cancelled()); +} - grpc_call_unref(c); - grpc_call_unref(s); +TEST_P(RetryTest, RetryCancellation) { + TestRetryCancellation(*this, std::make_unique()); } -void retry_cancellation(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) { - test_retry_cancellation(config, cancellation_modes[i]); - } +TEST_P(RetryTest, RetryDeadline) { + TestRetryCancellation(*this, std::make_unique()); } -void retry_cancellation_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_disabled.cc b/test/core/end2end/tests/retry_disabled.cc index f0257e3a3ba..223f8f505b2 100644 --- a/test/core/end2end/tests/retry_disabled.cc +++ b/test/core/end2end/tests/retry_disabled.cc @@ -16,193 +16,75 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't retry when retries are disabled via the // GRPC_ARG_ENABLE_RETRIES channel arg, even when there is retry // configuration in the service config. // - 1 retry allowed for ABORTED status // - first attempt returns ABORTED but does not retry -static void test_retry_disabled(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_RETRIES), 0), - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_disabled", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_disabled(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_disabled(config); +TEST_P(RetryTest, RetryDisabled) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_ENABLE_RETRIES, false) + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_disabled_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc index 04ab3ede620..f6cfa31f21b 100644 --- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc +++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc @@ -14,37 +14,20 @@ // limitations under the License. // -#include -#include +#include -#include -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests the case where the retry buffer size is exceeded during backoff. // - 1 retry allowed for ABORTED status @@ -53,217 +36,80 @@ static std::unique_ptr begin_test( // - server sends ABORTED, client goes into backoff delay // - client sends a 100 KiB message, thus exceeding the buffer size limit // - retry attempt gets ABORTED but is not retried -static void test_retry_exceeds_buffer_size_in_delay( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - const size_t buf_size = 102401; - char* buf = static_cast(gpr_malloc(buf_size * sizeof(*buf))); - memset(buf, 'a', buf_size - 1); - buf[buf_size - 1] = '\0'; - grpc_slice request_payload_slice = grpc_slice_from_static_string(buf); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"2s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), 102400), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_exceeds_buffer_size_in_delay", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(15000); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details1 = grpc_slice_from_static_string("message1"); - grpc_slice status_details2 = grpc_slice_from_static_string("message2"); - +TEST_P(RetryTest, RetryExceedsBufferSizeInDelay) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"2s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}") + .Set(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE, 102400)); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(15)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client sends initial metadata and starts the recv ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvMessage(server_message) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); // Server gets a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + absl::optional s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server sends ABORTED. This tells the client to retry. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details1; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + IncomingCloseOnServer client_close; + s->NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "message1", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + s.reset(); // Do a bit more polling, to make sure the client sees status from the // first attempt. (Note: This polls for 1s, which is less than the // retry initial backoff time of 2s from the service config above.) - cqv.VerifyEmpty(); - + Step(Duration::Seconds(1)); // Client sends a message that puts it over the buffer size limit. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - + c.NewBatch(2).SendMessage(std::string(102401, 'a')).SendCloseFromClient(); + Expect(2, true); + Step(); // Server gets another call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - + auto s2 = RequestCall(201); + Expect(201, true); + Step(); // Server again sends ABORTED. But this time, the client won't retry, // since the call has been committed by exceeding the buffer size. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details2; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "message2")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); - - gpr_free(buf); -} - -void retry_exceeds_buffer_size_in_delay(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_exceeds_buffer_size_in_delay(config); + IncomingCloseOnServer client_close2; + s2.NewBatch(202) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "message2", {}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "message2"); + EXPECT_EQ(s2.method(), "/service/method"); + EXPECT_FALSE(client_close2.was_cancelled()); } -void retry_exceeds_buffer_size_in_delay_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc index 06889773bed..5a3109c5582 100644 --- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc +++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc @@ -16,36 +16,18 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't make any further attempts after we exceed the // max buffer size. @@ -53,160 +35,57 @@ static std::unique_ptr begin_test( // - buffer size set to 2 bytes // - client sends a 3-byte message // - first attempt gets ABORTED but is not retried -static void test_retry_exceeds_buffer_size_in_initial_batch( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), 2), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_exceeds_buffer_size_in_initial_batch", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_exceeds_buffer_size_in_initial_batch( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_exceeds_buffer_size_in_initial_batch(config); +TEST_P(RetryTest, RetryExceedsBufferSizeInInitialBatch) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}") + .Set(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE, 2)); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_exceeds_buffer_size_in_initial_batch_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc index a8f8c99f43d..feab3941206 100644 --- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc +++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc @@ -16,37 +16,20 @@ // // -#include -#include +#include -#include -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Similar to the retry_exceeds_buffer_size_in_initial_batch test, but we // don't exceed the buffer size until the second batch. @@ -54,175 +37,59 @@ static std::unique_ptr begin_test( // - buffer size set to 100 KiB (larger than initial metadata) // - client sends a 100 KiB message // - first attempt gets ABORTED but is not retried -static void test_retry_exceeds_buffer_size_in_subsequent_batch( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - const size_t buf_size = 102401; - char* buf = static_cast(gpr_malloc(buf_size * sizeof(*buf))); - memset(buf, 'a', buf_size - 1); - buf[buf_size - 1] = '\0'; - // TODO(markdroth): buf is not a static string, so fix the next line - grpc_slice request_payload_slice = grpc_slice_from_static_string(buf); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), 102400), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_exceeds_buffer_size_in_subsequent_batch", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); - - gpr_free(buf); -} - -void retry_exceeds_buffer_size_in_subsequent_batch( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_exceeds_buffer_size_in_subsequent_batch(config); +TEST_P(RetryTest, RetryExceedsBufferSizeInSubsequentBatch) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}") + .Set(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE, 102400)); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + c.NewBatch(1).SendInitialMetadata({}); + Expect(1, true); + Step(); + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + IncomingStatusOnClient server_status; + c.NewBatch(2) + .SendMessage(std::string(102400, 'a')) + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_lb_drop.cc b/test/core/end2end/tests/retry_lb_drop.cc index 4b2a0b00499..88d48f5f95d 100644 --- a/test/core/end2end/tests/retry_lb_drop.cc +++ b/test/core/end2end/tests/retry_lb_drop.cc @@ -14,11 +14,7 @@ // limitations under the License. // -#include -#include - #include -#include #include #include #include @@ -26,26 +22,21 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include #include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/json/json.h" #include "src/core/lib/load_balancing/lb_policy.h" #include "src/core/lib/load_balancing/lb_policy_factory.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" #include "test/core/util/test_lb_policies.h" namespace grpc_core { @@ -105,139 +96,62 @@ void RegisterDropPolicy(CoreConfiguration::Builder* builder) { std::make_unique()); } -} // namespace -} // namespace grpc_core - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - // Tests that we don't retry when the LB policy drops a call, // even when there is retry configuration in the service config. // - 1 retry allowed for UNAVAILABLE status // - first attempt returns UNAVAILABLE due to LB drop but does not retry -static void test_retry_lb_drop(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - std::vector pick_args_seen; - grpc_core::g_pick_args_vector = &pick_args_seen; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"loadBalancingConfig\": [ {\n" - " \"test_pick_args_lb\": {}\n" - " } ],\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"UNAVAILABLE\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_lb_drop", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == - grpc_slice_str_cmp(details, "Call dropped by drop LB policy")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - - gpr_log(GPR_INFO, "NUMBER OF LB PICKS: %" PRIuPTR, pick_args_seen.size()); - GPR_ASSERT(pick_args_seen.size() == 1); - - grpc_core::g_pick_args_vector = nullptr; -} - -void retry_lb_drop(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_lb_drop(config); +TEST_P(RetryTest, RetryLbDrop) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + RegisterTestPickArgsLoadBalancingPolicy( + builder, + [](const PickArgsSeen& pick_args) { + GPR_ASSERT(g_pick_args_vector != nullptr); + g_pick_args_vector->push_back(pick_args); + }, + kDropPolicyName); + }); + CoreConfiguration::RegisterBuilder(RegisterDropPolicy); + std::vector pick_args_seen; + g_pick_args_vector = &pick_args_seen; + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"loadBalancingConfig\": [ {\n" + " \"test_pick_args_lb\": {}\n" + " } ],\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"UNAVAILABLE\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + EXPECT_EQ(server_status.message(), "Call dropped by drop LB policy"); + EXPECT_EQ(pick_args_seen.size(), 1); + g_pick_args_vector = nullptr; } -void retry_lb_drop_pre_init(void) { - grpc_core::CoreConfiguration::RegisterBuilder( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::RegisterTestPickArgsLoadBalancingPolicy( - builder, - [](const grpc_core::PickArgsSeen& pick_args) { - GPR_ASSERT(grpc_core::g_pick_args_vector != nullptr); - grpc_core::g_pick_args_vector->push_back(pick_args); - }, - grpc_core::kDropPolicyName); - }); - grpc_core::CoreConfiguration::RegisterBuilder(grpc_core::RegisterDropPolicy); -} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_lb_fail.cc b/test/core/end2end/tests/retry_lb_fail.cc index b3ebde65e82..931a01aad53 100644 --- a/test/core/end2end/tests/retry_lb_fail.cc +++ b/test/core/end2end/tests/retry_lb_fail.cc @@ -14,159 +14,71 @@ // limitations under the License. // -#include - #include -#include -#include #include "absl/status/status.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" #include "test/core/util/test_lb_policies.h" +namespace grpc_core { namespace { - std::atomic g_num_lb_picks; -} // namespace - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - // Tests that we retry properly when the LB policy fails the call before // it ever gets to the transport, even if recv_trailing_metadata isn't // started by the application until after the LB pick fails. // - 1 retry allowed for ABORTED status // - on first attempt, LB policy fails with ABORTED before application // starts recv_trailing_metadata op -static void test_retry_lb_fail(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - +TEST_P(RetryTest, RetryLbFail) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + RegisterFailLoadBalancingPolicy( + builder, absl::UnavailableError("LB pick failed"), &g_num_lb_picks); + }); g_num_lb_picks.store(0, std::memory_order_relaxed); - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_RETRIES), 1), - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"loadBalancingConfig\": [ {\n" - " \"fail_lb\": {}\n" - " } ],\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"UNAVAILABLE\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_lb_fail", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(1), false); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "LB pick failed")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - - int num_picks = g_num_lb_picks.load(std::memory_order_relaxed); - gpr_log(GPR_INFO, "NUM LB PICKS: %d", num_picks); - GPR_ASSERT(num_picks == 2); -} - -void retry_lb_fail(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_lb_fail(config); + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_ENABLE_RETRIES, true) + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"loadBalancingConfig\": [ {\n" + " \"fail_lb\": {}\n" + " } ],\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"UNAVAILABLE\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + c.NewBatch(1).SendInitialMetadata({}); + Expect(1, false); + Step(); + IncomingStatusOnClient server_status; + c.NewBatch(2).RecvStatusOnClient(server_status); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + EXPECT_EQ(server_status.message(), "LB pick failed"); + EXPECT_EQ(g_num_lb_picks.load(std::memory_order_relaxed), 2); } -void retry_lb_fail_pre_init(void) { - grpc_core::CoreConfiguration::RegisterBuilder( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::RegisterFailLoadBalancingPolicy( - builder, absl::UnavailableError("LB pick failed"), &g_num_lb_picks); - }); -} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_non_retriable_status.cc b/test/core/end2end/tests/retry_non_retriable_status.cc index ee36fbe716d..b968c5e2169 100644 --- a/test/core/end2end/tests/retry_non_retriable_status.cc +++ b/test/core/end2end/tests/retry_non_retriable_status.cc @@ -16,191 +16,70 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't retry for non-retryable status codes. // - 1 retry allowed for ABORTED status // - first attempt gets INVALID_ARGUMENT, so no retry is done -static void test_retry_non_retriable_status( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_non_retriable_status", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_INVALID_ARGUMENT; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_non_retriable_status(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_non_retriable_status(config); +TEST_P(RetryTest, RetryNonRetriableStatus) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_INVALID_ARGUMENT, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_INVALID_ARGUMENT); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } - -void retry_non_retriable_status_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc index c1c8e4d79bb..a813df51a75 100644 --- a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc +++ b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc @@ -16,206 +16,73 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't retry for non-retryable status codes, even if // status is received before the recv_trailing_metadata op is started. // - 1 retry allowed for ABORTED status // - first attempt gets INVALID_ARGUMENT, so no retry is done -static void -test_retry_non_retriable_status_before_recv_trailing_metadata_started( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test( - config, - "retry_non_retriable_status_before_recv_trailing_metadata_started", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_INVALID_ARGUMENT; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); +TEST_P(RetryTest, RetryNonRetriableStatusBeforeRecvTrailingMetadataStarted) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_INVALID_ARGUMENT, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + IncomingMessage server_message; + IncomingStatusOnClient server_status; + c.NewBatch(2).RecvMessage(server_message).RecvStatusOnClient(server_status); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_INVALID_ARGUMENT); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_non_retriable_status_before_recv_trailing_metadata_started( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_non_retriable_status_before_recv_trailing_metadata_started(config); -} - -void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init() { -} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_per_attempt_recv_timeout.cc b/test/core/end2end/tests/retry_per_attempt_recv_timeout.cc index 39e1debd7b6..9aa4779d7a1 100644 --- a/test/core/end2end/tests/retry_per_attempt_recv_timeout.cc +++ b/test/core/end2end/tests/retry_per_attempt_recv_timeout.cc @@ -14,299 +14,114 @@ // limitations under the License. // -#include - -#include #include -#include -#include #include "absl/strings/str_format.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests perAttemptRecvTimeout: // - 2 retries allowed for ABORTED status // - first attempt does not receive a response until after perAttemptRecvTimeout // - second attempt returns ABORTED // - third attempt returns OK -static void test_retry_per_attempt_recv_timeout( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_call* s0; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - std::string service_config = absl::StrFormat( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"perAttemptRecvTimeout\": \"%ds\",\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}", - 2 * grpc_test_slowdown_factor()); - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1), - grpc_channel_arg_string_create(const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast(service_config.c_str())), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "test_retry_per_attempt_recv_timeout", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - +TEST_P(RetryTest, RetryPerAttemptRecvTimeout) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING, true) + .Set( + GRPC_ARG_SERVICE_CONFIG, + absl::StrFormat( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"perAttemptRecvTimeout\": \"%ds\",\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}", + 2 * grpc_test_slowdown_factor()))); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(10)).Create(); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); // Server gets a call but does not respond to the call. - error = grpc_server_request_call(f->server(), &s0, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + absl::optional s0 = RequestCall(101); + Expect(101, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was not sent in the // initial attempt. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + EXPECT_EQ(s0->GetInitialMetadata("grpc-previous-rpc-attempts"), + absl::nullopt); // Server gets a second call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - + absl::optional s1 = RequestCall(201); + Expect(201, true); + Step(); // Now we can unref the first call. - grpc_call_unref(s0); - + s0.reset(); // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - bool found_retry_header = false; - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - if (grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))) { - GPR_ASSERT(grpc_slice_eq(request_metadata_recv.metadata[i].value, - grpc_slice_from_static_string("1"))); - found_retry_header = true; - break; - } - } - GPR_ASSERT(found_retry_header); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + EXPECT_EQ(s1->GetInitialMetadata("grpc-previous-rpc-attempts"), "1"); + EXPECT_NE(s1->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server sends status ABORTED. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + IncomingCloseOnServer client_close1; + s1->NewBatch(202) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close1); + Expect(202, true); + Step(); + s1.reset(); // Server gets a third call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(301)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(301), true); - cqv.Verify(); - + auto s2 = RequestCall(301); + Expect(301, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - found_retry_header = false; - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - if (grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))) { - GPR_ASSERT(grpc_slice_eq(request_metadata_recv.metadata[i].value, - grpc_slice_from_static_string("2"))); - found_retry_header = true; - break; - } - } - GPR_ASSERT(found_retry_header); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(302), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + EXPECT_EQ(s2.GetInitialMetadata("grpc-previous-rpc-attempts"), "2"); + IncomingMessage client_message2; + s2.NewBatch(302).RecvMessage(client_message2); // Server sends OK status. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(303), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(302), true); - cqv.Expect(grpc_core::CqVerifier::tag(303), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); + IncomingCloseOnServer client_close2; + s2.NewBatch(303) + .SendInitialMetadata({}) + .SendMessage("bar") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}) + .RecvCloseOnServer(client_close2); + Expect(302, true); + Expect(303, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s2.method(), "/service/method"); + EXPECT_FALSE(client_close2.was_cancelled()); } - -void retry_per_attempt_recv_timeout(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_per_attempt_recv_timeout(config); -} - -void retry_per_attempt_recv_timeout_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc b/test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc index bdb1696f86c..4bbc3efbd54 100644 --- a/test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc +++ b/test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc @@ -14,207 +14,85 @@ // limitations under the License. // -#include - -#include #include -#include -#include #include "absl/strings/str_format.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests perAttemptRecvTimeout: // - 1 retry allowed for ABORTED status // - both attempts do not receive a response until after perAttemptRecvTimeout -static void test_retry_per_attempt_recv_timeout_on_last_attempt( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_call* s0; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - - std::string service_config = absl::StrFormat( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"perAttemptRecvTimeout\": \"%ds\",\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}", - 2 * grpc_test_slowdown_factor()); - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING), 1), - grpc_channel_arg_string_create(const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast(service_config.c_str())), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "test_retry_per_attempt_recv_timeout_on_last_attempt", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - +TEST_P(RetryTest, RetryPerAttemptRecvTimeoutOnLastAttempt) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_EXPERIMENTAL_ENABLE_HEDGING, true) + .Set( + GRPC_ARG_SERVICE_CONFIG, + absl::StrFormat( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"perAttemptRecvTimeout\": \"%ds\",\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}", + 2 * grpc_test_slowdown_factor()))); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(10)).Create(); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); // Server gets a call but does not respond to the call. - error = grpc_server_request_call(f->server(), &s0, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + absl::optional s0 = RequestCall(101); + Expect(101, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was not sent in the // initial attempt. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - + EXPECT_EQ(s0->GetInitialMetadata("grpc-previous-rpc-attempts"), + absl::nullopt); // Server gets a second call, which it also does not respond to. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - + absl::optional s1 = RequestCall(201); + Expect(201, true); + Step(); // Now we can unref the first call. - grpc_call_unref(s0); - + s0.reset(); // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - bool found_retry_header = false; - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - if (grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))) { - GPR_ASSERT(grpc_slice_eq(request_metadata_recv.metadata[i].value, - grpc_slice_from_static_string("1"))); - found_retry_header = true; - break; - } - } - GPR_ASSERT(found_retry_header); - + EXPECT_EQ(s1->GetInitialMetadata("grpc-previous-rpc-attempts"), "1"); // Client sees call completion. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_CANCELLED); - GPR_ASSERT( - 0 == grpc_slice_str_cmp(details, "retry perAttemptRecvTimeout exceeded")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_per_attempt_recv_timeout_on_last_attempt( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_per_attempt_recv_timeout_on_last_attempt(config); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); + EXPECT_EQ(server_status.message(), "retry perAttemptRecvTimeout exceeded"); + EXPECT_EQ(s1->method(), "/service/method"); } -void retry_per_attempt_recv_timeout_on_last_attempt_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_recv_initial_metadata.cc b/test/core/end2end/tests/retry_recv_initial_metadata.cc index 426512db1f0..76affef977a 100644 --- a/test/core/end2end/tests/retry_recv_initial_metadata.cc +++ b/test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -16,153 +16,60 @@ // // -#include +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that receiving initial metadata commits the call. // - 1 retry allowed for ABORTED status // - first attempt receives initial metadata before trailing metadata, // so no retry is done even though status was ABORTED -static void test_retry_recv_initial_metadata( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - grpc_metadata initial_metadata_from_server = { - grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - {{nullptr, nullptr, nullptr, nullptr}}}; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_recv_initial_metadata", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - +TEST_P(RetryTest, RetryRecvInitialMetadata) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server sends initial metadata in its own batch, before sending // trailing metadata. // Ideally, this would not require actually sending any metadata @@ -170,59 +77,21 @@ static void test_retry_recv_initial_metadata( // tests, where the proxy may wind up combining the batches, depending // on timing. Sending a metadata entry ensures that the transport // won't send a Trailers-Only response, even if the batches are combined. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 1; - op->data.send_initial_metadata.metadata = &initial_metadata_from_server; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_recv_initial_metadata(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_recv_initial_metadata(config); + s.NewBatch(102).SendInitialMetadata({{"key1", "val1"}}); + Expect(102, true); + Step(); + IncomingCloseOnServer client_close; + s.NewBatch(103) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_recv_initial_metadata_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_recv_message.cc b/test/core/end2end/tests/retry_recv_message.cc index f28804c8665..13a9a49eb1e 100644 --- a/test/core/end2end/tests/retry_recv_message.cc +++ b/test/core/end2end/tests/retry_recv_message.cc @@ -16,193 +16,73 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that receiving a message commits the call. // - 1 retry allowed for ABORTED status // - first attempt receives a message and therefore does not retry even // though the final status is ABORTED -static void test_retry_recv_message(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_recv_message", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_recv_message(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_recv_message(config); +TEST_P(RetryTest, RetryRecvMessage) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(103) + .SendInitialMetadata({}) + .SendMessage("bar") + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_recv_message_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_recv_message_replay.cc b/test/core/end2end/tests/retry_recv_message_replay.cc index ca3ad5b1b7f..3e77b28aeb0 100644 --- a/test/core/end2end/tests/retry_recv_message_replay.cc +++ b/test/core/end2end/tests/retry_recv_message_replay.cc @@ -16,213 +16,30 @@ // // -#include - -#include -#include #include #include "absl/status/status.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests the fix for a bug found in real-world code where recv_message -// was incorrectly replayed on a call attempt that it was already sent -// to when the recv_message completion had already been returned but was -// deferred at the point where recv_trailing_metadata was started from -// the surface. This resulted in ASAN failures caused by not unreffing -// a grpc_error. -static void test_retry_recv_message_replay( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_recv_message_replay", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - // Start a batch containing send_initial_metadata and recv_initial_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Start a batch containing recv_message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Start a batch containing recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Server should get a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - // Server fails with status ABORTED. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // In principle, the server batch should complete before the client - // batches, but in the proxy fixtures, there are multiple threads - // involved, so the completion order tends to be a little racy. - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} +namespace grpc_core { namespace { // A filter that, for the first call it sees, will fail the batch @@ -260,7 +77,7 @@ class FailFirstSendOpFilter { batch, grpc_error_set_int( GRPC_ERROR_CREATE("FailFirstSendOpFilter failing batch"), - grpc_core::StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), + StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), calld->call_combiner_); return; } @@ -271,7 +88,7 @@ class FailFirstSendOpFilter { explicit CallData(const grpc_call_element_args* args) : call_combiner_(args->call_combiner) {} - grpc_core::CallCombiner* call_combiner_; + CallCombiner* call_combiner_; bool fail_ = false; }; @@ -305,28 +122,80 @@ grpc_channel_filter FailFirstSendOpFilter::kFilterVtable = { "FailFirstSendOpFilter", }; -} // namespace - -void retry_recv_message_replay(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage( - GRPC_CLIENT_SUBCHANNEL, 0, - [](grpc_core::ChannelStackBuilder* builder) { - // Skip on proxy (which explicitly disables retries). - if (!builder->channel_args() - .GetBool(GRPC_ARG_ENABLE_RETRIES) - .value_or(true)) { - return true; - } - // Install filter. - builder->PrependFilter(&FailFirstSendOpFilter::kFilterVtable); - return true; - }); - }, - [config] { test_retry_recv_message_replay(config); }); +// Tests the fix for a bug found in real-world code where recv_message +// was incorrectly replayed on a call attempt that it was already sent +// to when the recv_message completion had already been returned but was +// deferred at the point where recv_trailing_metadata was started from +// the surface. This resulted in ASAN failures caused by not unreffing +// a grpc_error. +TEST_P(RetryTest, RetryRecvMessageReplay) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + GRPC_CLIENT_SUBCHANNEL, 0, [](ChannelStackBuilder* builder) { + // Skip on proxy (which explicitly disables retries). + if (!builder->channel_args() + .GetBool(GRPC_ARG_ENABLE_RETRIES) + .value_or(true)) { + return true; + } + // Install filter. + builder->PrependFilter(&FailFirstSendOpFilter::kFilterVtable); + return true; + }); + }); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + // Start a batch containing send_initial_metadata and recv_initial_metadata. + IncomingMetadata server_initial_metadata; + c.NewBatch(1).SendInitialMetadata({}).RecvInitialMetadata( + server_initial_metadata); + // Start a batch containing recv_message. + IncomingMessage server_message; + c.NewBatch(2).RecvMessage(server_message); + // Start a batch containing recv_trailing_metadata. + IncomingStatusOnClient server_status; + c.NewBatch(3).RecvStatusOnClient(server_status); + // Server should get a call. + auto s = RequestCall(101); + Expect(101, true); + Step(); + // Server fails with status ABORTED. + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + // In principle, the server batch should complete before the client + // batches, but in the proxy fixtures, there are multiple threads + // involved, so the completion order tends to be a little racy. + Expect(102, true); + Expect(1, true); + Expect(2, true); + Expect(3, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_recv_message_replay_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc b/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc index 7fbccf2fcbb..26750545ba0 100644 --- a/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc +++ b/test/core/end2end/tests/retry_recv_trailing_metadata_error.cc @@ -14,214 +14,30 @@ // limitations under the License. // -#include - -#include -#include #include #include "absl/status/status.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests that we honor the error passed to recv_trailing_metadata_ready -// when determining the call's status, even if the op completion runs before -// the recv_trailing_metadata op is started from the surface. -// - 1 retry allowed for ABORTED status -// - server returns ABORTED, but filter overwrites to INVALID_ARGUMENT, -// so no retry is done -static void test_retry_recv_trailing_metadata_error( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_recv_trailing_metadata_error", - &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "injected error")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} +namespace grpc_core { namespace { // A filter that returns recv_trailing_metadata_ready with an error. @@ -266,11 +82,11 @@ class InjectStatusFilter { static void RecvTrailingMetadataReady(void* arg, grpc_error_handle /*error*/) { auto* calld = static_cast(arg); - grpc_core::Closure::Run( - DEBUG_LOCATION, calld->original_recv_trailing_metadata_ready_, - grpc_error_set_int(GRPC_ERROR_CREATE("injected error"), - grpc_core::StatusIntProperty::kRpcStatus, - GRPC_STATUS_INVALID_ARGUMENT)); + Closure::Run(DEBUG_LOCATION, + calld->original_recv_trailing_metadata_ready_, + grpc_error_set_int(GRPC_ERROR_CREATE("injected error"), + StatusIntProperty::kRpcStatus, + GRPC_STATUS_INVALID_ARGUMENT)); } grpc_closure recv_trailing_metadata_ready_; @@ -301,7 +117,7 @@ grpc_channel_filter InjectStatusFilter::kFilterVtable = { "InjectStatusFilter", }; -bool AddFilter(grpc_core::ChannelStackBuilder* builder) { +bool AddFilter(ChannelStackBuilder* builder) { // Skip on proxy (which explicitly disables retries). if (!builder->channel_args() .GetBool(GRPC_ARG_ENABLE_RETRIES) @@ -313,17 +129,67 @@ bool AddFilter(grpc_core::ChannelStackBuilder* builder) { return true; } -} // namespace - -void retry_recv_trailing_metadata_error(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0, - AddFilter); - }, - [config] { test_retry_recv_trailing_metadata_error(config); }); +// Tests that we honor the error passed to recv_trailing_metadata_ready +// when determining the call's status, even if the op completion runs before +// the recv_trailing_metadata op is started from the surface. +// - 1 retry allowed for ABORTED status +// - server returns ABORTED, but filter overwrites to INVALID_ARGUMENT, +// so no retry is done +TEST_P(RetryTest, RetryRecvTrailingMetadataError) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage(GRPC_CLIENT_SUBCHANNEL, 0, + AddFilter); + }); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + IncomingStatusOnClient server_status; + c.NewBatch(2).RecvStatusOnClient(server_status); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_INVALID_ARGUMENT); + EXPECT_EQ(server_status.message(), "injected error"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_recv_trailing_metadata_error_pre_init() {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_send_initial_metadata_refs.cc b/test/core/end2end/tests/retry_send_initial_metadata_refs.cc index cf138afdcd2..373ed57d87f 100644 --- a/test/core/end2end/tests/retry_send_initial_metadata_refs.cc +++ b/test/core/end2end/tests/retry_send_initial_metadata_refs.cc @@ -16,303 +16,112 @@ // // -#include - -#include -#include #include -#include +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" + #include -#include #include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we hold refs to send_initial_metadata payload while // cached, even after the caller has released its refs: // - 2 retries allowed for ABORTED status // - first attempt returns ABORTED // - second attempt returns OK -static void test_retry_send_initial_metadata_refs( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array client_send_initial_metadata; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_send_initial_metadata_refs", &client_args, - nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&client_send_initial_metadata); - client_send_initial_metadata.count = 2; - client_send_initial_metadata.metadata = static_cast( - gpr_malloc(client_send_initial_metadata.count * sizeof(grpc_metadata))); - // First element is short enough for slices to be inlined. - client_send_initial_metadata.metadata[0].key = - grpc_slice_from_copied_string(std::string("foo").c_str()); - client_send_initial_metadata.metadata[0].value = - grpc_slice_from_copied_string(std::string("bar").c_str()); - // Second element requires slice allocation. - client_send_initial_metadata.metadata[1].key = grpc_slice_from_copied_string( - std::string(GRPC_SLICE_INLINED_SIZE + 1, 'x').c_str()); - client_send_initial_metadata.metadata[1].value = - grpc_slice_from_copied_string( - std::string(GRPC_SLICE_INLINED_SIZE + 1, 'y').c_str()); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = client_send_initial_metadata.count; - op->data.send_initial_metadata.metadata = - client_send_initial_metadata.metadata; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - for (size_t i = 0; i < client_send_initial_metadata.count; ++i) { - grpc_slice_unref(client_send_initial_metadata.metadata[i].key); - grpc_slice_unref(client_send_initial_metadata.metadata[i].value); - } - grpc_metadata_array_destroy(&client_send_initial_metadata); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - +TEST_P(RetryTest, RetrySendInitialMetadataRefs) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + c.NewBatch(1) + .SendInitialMetadata( + {// First element is short enough for slices to be inlined. + {"foo", "bar"}, + // Second element requires slice allocation. + {std::string(GRPC_SLICE_INLINED_SIZE + 1, 'x'), + std::string(GRPC_SLICE_INLINED_SIZE + 1, 'y')}}) + .SendMessage("foo") + .SendCloseFromClient(); + Expect(1, true); + Step(); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(2) + .RecvMessage(server_message) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was not sent in the // initial attempt. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - + EXPECT_EQ(s.GetInitialMetadata("grpc-previous-rpc-attempts"), absl::nullopt); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + auto s2 = RequestCall(201); + Expect(201, true); + Step(); // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - GPR_ASSERT(contains_metadata_slices( - &request_metadata_recv, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"), - grpc_slice_from_static_string("1"))); + EXPECT_EQ(s2.GetInitialMetadata("grpc-previous-rpc-attempts"), "1"); // It should also contain the initial metadata, even though the client // freed it already. - GPR_ASSERT(contains_metadata(&request_metadata_recv, "foo", "bar")); - GPR_ASSERT( - contains_metadata(&request_metadata_recv, - std::string(GRPC_SLICE_INLINED_SIZE + 1, 'x').c_str(), - std::string(GRPC_SLICE_INLINED_SIZE + 1, 'y').c_str())); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(203), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(203), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_send_initial_metadata_refs(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_send_initial_metadata_refs(config); + EXPECT_EQ(s2.GetInitialMetadata("foo"), "bar"); + EXPECT_EQ( + s2.GetInitialMetadata(std::string(GRPC_SLICE_INLINED_SIZE + 1, 'x')), + std::string(GRPC_SLICE_INLINED_SIZE + 1, 'y')); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage client_message; + s2.NewBatch(202).RecvMessage(client_message); + IncomingCloseOnServer client_close2; + s2.NewBatch(203) + .SendInitialMetadata({}) + .SendMessage("bar") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(203, true); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_send_initial_metadata_refs_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_send_op_fails.cc b/test/core/end2end/tests/retry_send_op_fails.cc index 46bc7fdfda0..befd60ff5c6 100644 --- a/test/core/end2end/tests/retry_send_op_fails.cc +++ b/test/core/end2end/tests/retry_send_op_fails.cc @@ -16,226 +16,30 @@ // // -#include - -#include -#include #include #include "absl/status/status.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests failure on a send op batch: -// - 2 retries allowed for ABORTED status -// - on the first call attempt, the batch containing the -// send_initial_metadata op fails, and then the call returns ABORTED, -// all without ever going out on the wire -// - second attempt returns ABORTED but does not retry, because only 2 -// attempts are allowed -static void test_retry_send_op_fails(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_send_op_fails", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - // Start a batch containing send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Start a batch containing recv ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Client send ops should now complete. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - // Server should get a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - // Server fails with status ABORTED. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // In principle, the server batch should complete before the client - // recv ops batch, but in the proxy fixtures, there are multiple threads - // involved, so the completion order tends to be a little racy. - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. - bool found_retry_header = false; - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - if (grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))) { - GPR_ASSERT(grpc_slice_eq(request_metadata_recv.metadata[i].value, - grpc_slice_from_static_string("1"))); - found_retry_header = true; - break; - } - } - GPR_ASSERT(found_retry_header); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} +namespace grpc_core { namespace { // A filter that, for the first call it sees, will fail all batches except @@ -274,7 +78,7 @@ class FailFirstCallFilter { batch, grpc_error_set_int( GRPC_ERROR_CREATE("FailFirstCallFilter failing batch"), - grpc_core::StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), + StatusIntProperty::kRpcStatus, GRPC_STATUS_ABORTED), calld->call_combiner_); return; } @@ -285,7 +89,7 @@ class FailFirstCallFilter { explicit CallData(const grpc_call_element_args* args) : call_combiner_(args->call_combiner) {} - grpc_core::CallCombiner* call_combiner_; + CallCombiner* call_combiner_; bool fail_ = false; }; @@ -319,28 +123,87 @@ grpc_channel_filter FailFirstCallFilter::kFilterVtable = { "FailFirstCallFilter", }; -} // namespace - -void retry_send_op_fails(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage( - GRPC_CLIENT_SUBCHANNEL, 0, - [](grpc_core::ChannelStackBuilder* builder) { - // Skip on proxy (which explicitly disables retries). - if (!builder->channel_args() - .GetBool(GRPC_ARG_ENABLE_RETRIES) - .value_or(true)) { - return true; - } - // Install filter. - builder->PrependFilter(&FailFirstCallFilter::kFilterVtable); - return true; - }); - }, - [config] { test_retry_send_op_fails(config); }); +// Tests failure on a send op batch: +// - 2 retries allowed for ABORTED status +// - on the first call attempt, the batch containing the +// send_initial_metadata op fails, and then the call returns ABORTED, +// all without ever going out on the wire +// - second attempt returns ABORTED but does not retry, because only 2 +// attempts are allowed +TEST_P(RetryTest, RetrySendOpFails) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + GRPC_CLIENT_SUBCHANNEL, 0, [](ChannelStackBuilder* builder) { + // Skip on proxy (which explicitly disables retries). + if (!builder->channel_args() + .GetBool(GRPC_ARG_ENABLE_RETRIES) + .value_or(true)) { + return true; + } + // Install filter. + builder->PrependFilter(&FailFirstCallFilter::kFilterVtable); + return true; + }); + }); + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + // Start a batch containing send ops. + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); + // Start a batch containing recv ops. + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + // Client send ops should now complete. + Expect(1, true); + Step(); + // Server should get a call. + auto s = RequestCall(101); + Expect(101, true); + Step(); + // Server fails with status ABORTED. + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + // In principle, the server batch should complete before the client + // recv ops batch, but in the proxy fixtures, there are multiple threads + // involved, so the completion order tends to be a little racy. + Expect(102, true); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + // Make sure the "grpc-previous-rpc-attempts" header was sent in the retry. + EXPECT_EQ(s.GetInitialMetadata("grpc-previous-rpc-attempts"), "1"); } -void retry_send_op_fails_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_send_recv_batch.cc b/test/core/end2end/tests/retry_send_recv_batch.cc index 779942b7074..4ec186d5ff7 100644 --- a/test/core/end2end/tests/retry_send_recv_batch.cc +++ b/test/core/end2end/tests/retry_send_recv_batch.cc @@ -14,191 +14,72 @@ // limitations under the License. // -#include +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests a scenario where there is a batch containing both a send op and // a recv op, where the send op completes but the recv op does not, and // then a subsequent recv op is started. This ensures that we do not // incorrectly attempt to replay the send op. -static void test_retry_send_recv_batch(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_send_recv_batch", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +TEST_P(RetryTest, RetrySendRecvBatch) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); // Client starts batch with send_initial_metadata and recv_initial_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMetadata server_initial_metadata; + c.NewBatch(1).SendInitialMetadata({}).RecvInitialMetadata( + server_initial_metadata); // Client starts a batch with send_message and recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingStatusOnClient server_status; + c.NewBatch(2).SendMessage("hello").RecvStatusOnClient(server_status); // Server gets a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + auto s = RequestCall(101); + Expect(101, true); + Step(); // Client starts a batch containing recv_message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMessage server_message; + c.NewBatch(3).RecvMessage(server_message); // Server fails the call with a non-retriable status. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_PERMISSION_DENIED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_PERMISSION_DENIED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_send_recv_batch(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_send_recv_batch(config); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_PERMISSION_DENIED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Expect(2, true); + Expect(3, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_send_recv_batch_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_server_pushback_delay.cc b/test/core/end2end/tests/retry_server_pushback_delay.cc index e645ba11c38..b58f1934167 100644 --- a/test/core/end2end/tests/retry_server_pushback_delay.cc +++ b/test/core/end2end/tests/retry_server_pushback_delay.cc @@ -16,262 +16,93 @@ // // -#include -#include - -#include -#include -#include - #include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/time.h" -#include "src/core/lib/slice/slice_internal.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we honor server push-back delay. // - 2 retries allowed for ABORTED status // - first attempt gets ABORTED with a long delay // - second attempt succeeds -static void test_retry_server_pushback_delay( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_metadata pushback_md; - memset(&pushback_md, 0, sizeof(pushback_md)); - pushback_md.key = grpc_slice_from_static_string("grpc-retry-pushback-ms"); - pushback_md.value = grpc_slice_from_static_string("2000"); - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_server_pushback_delay", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details1 = grpc_slice_from_static_string("message1"); - grpc_slice status_details2 = grpc_slice_from_static_string("message2"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(grpc_core::Duration::Seconds(20)); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 1; - op->data.send_status_from_server.trailing_metadata = &pushback_md; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details1; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - gpr_timespec before_retry = gpr_now(GPR_CLOCK_MONOTONIC); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - gpr_timespec after_retry = gpr_now(GPR_CLOCK_MONOTONIC); - gpr_timespec retry_delay = gpr_time_sub(after_retry, before_retry); +TEST_P(RetryTest, RetryServerPushbackDelay) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + absl::optional s = RequestCall(101); + Expect(101, true); + Step(Duration::Seconds(20)); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s->NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "message1", + {{"grpc-retry-pushback-ms", "2000"}}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + const auto before_retry = Timestamp::Now(); + s.reset(); + s.emplace(RequestCall(201)); + Expect(201, true); + Step(); + const auto after_retry = Timestamp::Now(); + const auto retry_delay = after_retry - before_retry; // Configured back-off was 1 second, server push-back said 2 seconds. // To avoid flakiness, we allow some fudge factor here. - gpr_log(GPR_INFO, "retry delay was {.tv_sec=%" PRId64 ", .tv_nsec=%d}", - retry_delay.tv_sec, retry_delay.tv_nsec); - GPR_ASSERT(retry_delay.tv_sec >= 1); - if (retry_delay.tv_sec == 1) { - GPR_ASSERT(retry_delay.tv_nsec >= 800000000); - } - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details2; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - gpr_log(GPR_INFO, "status=%d message=\"%s\"", status, - std::string(grpc_core::StringViewFromSlice(details)).c_str()); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "message2")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_server_pushback_delay(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_server_pushback_delay(config); + EXPECT_GE(retry_delay, Duration::Milliseconds(1800)); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close2; + s->NewBatch(202) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_OK, "message2", {}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "message2"); + EXPECT_EQ(s->method(), "/service/method"); + EXPECT_FALSE(client_close2.was_cancelled()); } -void retry_server_pushback_delay_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_server_pushback_disabled.cc b/test/core/end2end/tests/retry_server_pushback_disabled.cc index 43dfcd4d998..eb9dc962ce4 100644 --- a/test/core/end2end/tests/retry_server_pushback_disabled.cc +++ b/test/core/end2end/tests/retry_server_pushback_disabled.cc @@ -16,240 +16,87 @@ // // -#include +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't retry when disabled by server push-back. // - 2 retries allowed for ABORTED status // - first attempt gets ABORTED // - second attempt gets ABORTED but server push back disables retrying -static void test_retry_server_pushback_disabled( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_metadata pushback_md; - memset(&pushback_md, 0, sizeof(pushback_md)); - pushback_md.key = grpc_slice_from_static_string("grpc-retry-pushback-ms"); - pushback_md.value = grpc_slice_from_static_string("-1"); - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_server_pushback_disabled", &client_args, - nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 1; - op->data.send_status_from_server.trailing_metadata = &pushback_md; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_server_pushback_disabled(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_server_pushback_disabled(config); +TEST_P(RetryTest, RetryServerPushbackDisabled) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + absl::optional s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s->NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + s.reset(); + s.emplace(RequestCall(201)); + Expect(201, true); + Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close2; + s->NewBatch(202) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", + {{"grpc-retry-pushback-ms", "-1"}}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s->method(), "/service/method"); + EXPECT_FALSE(client_close2.was_cancelled()); } -void retry_server_pushback_disabled_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_streaming.cc b/test/core/end2end/tests/retry_streaming.cc index 6a4f8e0a47c..f6c366f3fe9 100644 --- a/test/core/end2end/tests/retry_streaming.cc +++ b/test/core/end2end/tests/retry_streaming.cc @@ -16,39 +16,25 @@ // // -#include - -#include -#include #include -#include +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channelz.h" -#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/surface/channel.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +using testing::HasSubstr; + +namespace grpc_core { +namespace { // Tests retrying a streaming RPC. This is the same as // the basic retry test, except that the client sends two messages on the @@ -59,345 +45,133 @@ static std::unique_ptr begin_test( // replayed ops happen under the hood -- they are not surfaced to the // C-core API, and therefore we have no way to inject the commit at the // right point. -static void test_retry_streaming(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice request2_payload_slice = grpc_slice_from_static_string("bar"); - grpc_slice request3_payload_slice = grpc_slice_from_static_string("baz"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("quux"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* request2_payload = - grpc_raw_byte_buffer_create(&request2_payload_slice, 1); - grpc_byte_buffer* request3_payload = - grpc_raw_byte_buffer_create(&request3_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* request2_payload_recv = nullptr; - grpc_byte_buffer* request3_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), - 1024 * 8), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_ENABLE_CHANNELZ), true), - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"))}; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_streaming", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - grpc_core::channelz::ChannelNode* channelz_channel = - grpc_channel_get_channelz_node(f->client()); - - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +TEST_P(RetryTest, RetryStreaming) { + InitServer(ChannelArgs()); + InitClient( + ChannelArgs() + .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024 * 8) + .Set(GRPC_ARG_ENABLE_CHANNELZ, true) + .Set(GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + channelz::ChannelNode* channelz_channel = + grpc_channel_get_channelz_node(client()); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client starts a batch for receiving initial metadata, a message, // and trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(1) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); // Client sends initial metadata and a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - + c.NewBatch(2).SendInitialMetadata({}).SendMessage("foo"); + Expect(2, true); + Step(); // Server gets a call with received initial metadata. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server receives a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - + IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); // Client sends a second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request2_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - + c.NewBatch(3).SendMessage("bar"); + Expect(3, true); + Step(); // Server receives the second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request2_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Verify(); - + IncomingMessage client_message2; + s.NewBatch(103).RecvMessage(client_message2); + Expect(103, true); + Step(); // Server sends both initial and trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - + IncomingCloseOnServer client_close; + s.NewBatch(104) + .RecvCloseOnServer(client_close) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}); + Expect(104, true); + Step(); // Clean up from first attempt. - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - request_payload_recv = nullptr; - GPR_ASSERT( - byte_buffer_eq_slice(request2_payload_recv, request2_payload_slice)); - grpc_byte_buffer_destroy(request2_payload_recv); - request2_payload_recv = nullptr; - + EXPECT_EQ(client_message.payload(), "foo"); + EXPECT_EQ(client_message2.payload(), "bar"); // Server gets a second call (the retry). - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + auto s2 = RequestCall(201); + Expect(201, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server receives a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Verify(); - + IncomingMessage client_message3; + s2.NewBatch(202).RecvMessage(client_message3); + Expect(202, true); + Step(); // Server receives a second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request2_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(203), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(203), true); - cqv.Verify(); - + IncomingMessage client_message4; + s2.NewBatch(203).RecvMessage(client_message4); + Expect(203, true); + Step(); // Client sends a third message and a close. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request3_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - + c.NewBatch(4).SendMessage("baz").SendCloseFromClient(); + Expect(4, true); + Step(); // Server receives a third message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request3_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(204), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(204), true); - cqv.Verify(); - + IncomingMessage client_message5; + s2.NewBatch(204).RecvMessage(client_message5); + Expect(204, true); + Step(); // Server receives a close and sends initial metadata, a message, and // trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - // Returning a retriable code, but because we are also sending a - // message, the client will commit instead of retrying again. - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(205), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(205), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - GPR_ASSERT(channelz_channel != nullptr); + IncomingCloseOnServer client_close2; + s2.NewBatch(205) + .RecvCloseOnServer(client_close2) + .SendInitialMetadata({}) + .SendMessage("quux") + // Returning a retriable code, but because we are also sending a + // message, the client will commit instead of retrying again. + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}); + Expect(205, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_NE(channelz_channel, nullptr); + // TODO(roth): consider using a regex check here. std::string json = channelz_channel->RenderJsonString(); - gpr_log(GPR_INFO, "%s", json.c_str()); - GPR_ASSERT(json.find("\"trace\"") != json.npos); - GPR_ASSERT(json.find("\"description\":\"Channel created\"") != json.npos); - GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos); - GPR_ASSERT(json.find("Resolution event") != json.npos); - GPR_ASSERT(json.find("Created new LB policy") != json.npos); - GPR_ASSERT(json.find("Service config changed") != json.npos); - GPR_ASSERT(json.find("Address list became non-empty") != json.npos); - GPR_ASSERT(json.find("Channel state change to CONNECTING") != json.npos); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request2_payload); - grpc_byte_buffer_destroy(request3_payload); - grpc_byte_buffer_destroy(response_payload); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - GPR_ASSERT( - byte_buffer_eq_slice(request2_payload_recv, request2_payload_slice)); - grpc_byte_buffer_destroy(request2_payload_recv); - GPR_ASSERT( - byte_buffer_eq_slice(request3_payload_recv, request3_payload_slice)); - grpc_byte_buffer_destroy(request3_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_streaming(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - - test_retry_streaming(config); + EXPECT_THAT(json, HasSubstr("\"trace\"")); + EXPECT_THAT(json, HasSubstr("\"description\":\"Channel created\"")); + EXPECT_THAT(json, HasSubstr("\"severity\":\"CT_INFO\"")); + EXPECT_THAT(json, HasSubstr("Resolution event")); + EXPECT_THAT(json, HasSubstr("Created new LB policy")); + EXPECT_THAT(json, HasSubstr("Service config changed")); + EXPECT_THAT(json, HasSubstr("Address list became non-empty")); + EXPECT_THAT(json, HasSubstr("Channel state change to CONNECTING")); + EXPECT_EQ(client_message3.payload(), "foo"); + EXPECT_EQ(client_message4.payload(), "bar"); + EXPECT_EQ(client_message5.payload(), "baz"); } -void retry_streaming_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_streaming_after_commit.cc b/test/core/end2end/tests/retry_streaming_after_commit.cc index d42c61c3558..897600cee64 100644 --- a/test/core/end2end/tests/retry_streaming_after_commit.cc +++ b/test/core/end2end/tests/retry_streaming_after_commit.cc @@ -16,295 +16,108 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we can continue to send/recv messages on a streaming call // after retries are committed. -static void test_retry_streaming_after_commit( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice request2_payload_slice = grpc_slice_from_static_string("bar"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("baz"); - grpc_slice response2_payload_slice = grpc_slice_from_static_string("quux"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* request2_payload = - grpc_raw_byte_buffer_create(&request2_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* response2_payload = - grpc_raw_byte_buffer_create(&response2_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* request2_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_byte_buffer* response2_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_streaming_after_commit", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +TEST_P(RetryTest, RetryStreamingAfterCommit) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client starts a batch for receiving initial metadata and a message. // This will commit retries. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMessage server_message; + IncomingMetadata server_initial_metadata; + c.NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); // Client sends initial metadata and a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - + c.NewBatch(3).SendInitialMetadata({}).SendMessage("foo"); + Expect(3, true); + Step(); // Server gets a call with received initial metadata. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server receives a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - + IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); // Server sends initial metadata and a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); + s.NewBatch(103).SendInitialMetadata({}).SendMessage("bar"); + Expect(103, true); // Client receives initial metadata and a message. - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - + Expect(2, true); + Step(); // Client sends a second message and a close. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request2_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - + c.NewBatch(4).SendMessage("baz").SendCloseFromClient(); + Expect(4, true); + Step(); // Server receives a second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request2_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - + IncomingMessage client_message2; + s.NewBatch(104).RecvMessage(client_message2); + Expect(104, true); + Step(); // Server receives a close, sends a second message, and sends status. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response2_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; // Returning a retriable code, but because retries are already // committed, the client will not retry. - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(105), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(105), true); - cqv.Verify(); - + IncomingCloseOnServer client_close; + s.NewBatch(105) + .RecvCloseOnServer(client_close) + .SendMessage("quux") + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}); + Expect(105, true); + Step(); // Client receives a second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response2_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(5), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(5), true); - cqv.Verify(); - + IncomingMessage server_message2; + c.NewBatch(5).RecvMessage(server_message2); + Expect(5, true); + Step(); // Client receives status. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request2_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(response2_payload); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - GPR_ASSERT( - byte_buffer_eq_slice(request2_payload_recv, request2_payload_slice)); - grpc_byte_buffer_destroy(request2_payload_recv); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - grpc_byte_buffer_destroy(response_payload_recv); - GPR_ASSERT( - byte_buffer_eq_slice(response2_payload_recv, response2_payload_slice)); - grpc_byte_buffer_destroy(response2_payload_recv); - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_streaming_after_commit(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_streaming_after_commit(config); + IncomingStatusOnClient server_status; + c.NewBatch(1).RecvStatusOnClient(server_status); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "foo"); + EXPECT_EQ(server_message.payload(), "bar"); + EXPECT_EQ(client_message2.payload(), "baz"); + EXPECT_EQ(server_message2.payload(), "quux"); } -void retry_streaming_after_commit_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc index 395e77d3966..6ad20811a84 100644 --- a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc +++ b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc @@ -16,340 +16,124 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we correctly clean up if the second attempt finishes // before we have finished replaying all of the send ops. -static void test_retry_streaming_succeeds_before_replay_finished( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice request2_payload_slice = grpc_slice_from_static_string("bar"); - grpc_slice request3_payload_slice = grpc_slice_from_static_string("baz"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("quux"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* request2_payload = - grpc_raw_byte_buffer_create(&request2_payload_slice, 1); - grpc_byte_buffer* request3_payload = - grpc_raw_byte_buffer_create(&request3_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* request2_payload_recv = nullptr; - grpc_byte_buffer* request3_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_streaming", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +TEST_P(RetryTest, RetryStreamSucceedsBeforeReplayFinished) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Client starts a batch for receiving initial metadata, a message, // and trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); // Client sends initial metadata and a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - + c.NewBatch(2).SendInitialMetadata({}).SendMessage("foo"); + Expect(2, true); + Step(); // Server gets a call with received initial metadata. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + absl::optional s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server receives a message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - + IncomingMessage client_message; + s->NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); // Client sends a second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request2_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - + c.NewBatch(3).SendMessage("bar"); + Expect(3, true); + Step(); // Server receives the second message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request2_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Verify(); - + IncomingMessage client_message2; + s->NewBatch(103).RecvMessage(client_message2); + Expect(103, true); + Step(); // Client sends a third message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request3_payload; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - + c.NewBatch(4).SendMessage("baz"); + Expect(4, true); + Step(); // Server receives the third message. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request3_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - + IncomingMessage client_message3; + s->NewBatch(104).RecvMessage(client_message3); + Expect(104, true); + Step(); // Server sends both initial and trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(105), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(105), true); - cqv.Verify(); - + IncomingCloseOnServer client_close; + s->NewBatch(105) + .RecvCloseOnServer(client_close) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}); + Expect(105, true); + Step(); // Clean up from first attempt. - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - request_payload_recv = nullptr; - GPR_ASSERT( - byte_buffer_eq_slice(request2_payload_recv, request2_payload_slice)); - grpc_byte_buffer_destroy(request2_payload_recv); - request2_payload_recv = nullptr; - GPR_ASSERT( - byte_buffer_eq_slice(request3_payload_recv, request3_payload_slice)); - grpc_byte_buffer_destroy(request3_payload_recv); - request3_payload_recv = nullptr; - + s.reset(); + EXPECT_EQ(client_message.payload(), "foo"); + EXPECT_EQ(client_message2.payload(), "bar"); + EXPECT_EQ(client_message3.payload(), "baz"); // Server gets a second call (the retry). - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - + s.emplace(RequestCall(201)); + Expect(201, true); + Step(); + EXPECT_NE(s->GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); // Server receives the first message (and does not receive any others). - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Verify(); - + IncomingMessage client_message4; + s->NewBatch(202).RecvMessage(client_message4); + Expect(202, true); + Step(); // Server sends initial metadata, a message, and trailing metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - // Returning a retriable code, but because we are also sending a - // message, the client will commit instead of retrying again. - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(205), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(205), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request2_payload); - grpc_byte_buffer_destroy(request3_payload); - grpc_byte_buffer_destroy(response_payload); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_streaming_succeeds_before_replay_finished( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_streaming_succeeds_before_replay_finished(config); + s->NewBatch(205) + .SendInitialMetadata({}) + .SendMessage("qux") + // Returning a retriable code, but because we are also sending a + // message, the client will commit instead of retrying again. + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}); + Expect(205, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s->method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message4.payload(), "foo"); } -void retry_streaming_succeeds_before_replay_finished_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_throttled.cc b/test/core/end2end/tests/retry_throttled.cc index 5438dc74c00..d8b5a2cb3b1 100644 --- a/test/core/end2end/tests/retry_throttled.cc +++ b/test/core/end2end/tests/retry_throttled.cc @@ -16,196 +16,78 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we don't retry when throttled. // - 1 retry allowed for ABORTED status // - first attempt gets ABORTED but is over limit, so no retry is done -static void test_retry_throttled(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ],\n" - // A single failure will cause us to be throttled. - // (This is not a very realistic config, but it works for the - // purposes of this test.) - " \"retryThrottling\": {\n" - " \"maxTokens\": 2,\n" - " \"tokenRatio\": 1.0\n" - " }\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_throttled", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -void retry_throttled(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_throttled(config); +TEST_P(RetryTest, RetryThrottled) { + InitServer(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ],\n" + // A single failure will cause us to be throttled. + // (This is not a very realistic config, but it works for the + // purposes of this test.) + " \"retryThrottling\": {\n" + " \"maxTokens\": 2,\n" + " \"tokenRatio\": 1.0\n" + " }\n" + "}")); + InitClient(ChannelArgs()); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } -void retry_throttled_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_too_many_attempts.cc b/test/core/end2end/tests/retry_too_many_attempts.cc index f4d1bcaa086..5dceb7ba935 100644 --- a/test/core/end2end/tests/retry_too_many_attempts.cc +++ b/test/core/end2end/tests/retry_too_many_attempts.cc @@ -16,232 +16,83 @@ // // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we stop retrying after the configured number of attempts. // - 1 retry allowed for ABORTED status // - first attempt gets ABORTED // - second attempt gets ABORTED but does not retry -static void test_retry_too_many_attempts(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_too_many_attempts", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_ABORTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); +TEST_P(RetryTest, RetryTooManyAttempts) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .RecvMessage(server_message) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Step(); + auto s2 = RequestCall(201); + + Expect(201, true); + Step(); + EXPECT_NE(s2.GetPeer(), absl::nullopt); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingCloseOnServer client_close2; + s2.NewBatch(202) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_ABORTED, "xyz", {}) + .RecvCloseOnServer(client_close2); + Expect(202, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_ABORTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s2.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } - -void retry_too_many_attempts(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_too_many_attempts(config); -} - -void retry_too_many_attempts_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_transparent_goaway.cc b/test/core/end2end/tests/retry_transparent_goaway.cc index 1b6486d0490..368588a6035 100644 --- a/test/core/end2end/tests/retry_transparent_goaway.cc +++ b/test/core/end2end/tests/retry_transparent_goaway.cc @@ -14,23 +14,14 @@ // limitations under the License. // -#include - -#include -#include #include #include "absl/status/status.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" @@ -38,6 +29,7 @@ #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" @@ -45,182 +37,9 @@ #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests transparent retries when the call was never sent out on the wire. -static void test_retry_transparent_goaway(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - auto f = begin_test(config, "retry_transparent_goaway", nullptr, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - // Start a batch containing send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Start a batch containing recv ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Client send ops should now complete. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - // Server should get a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - // Server receives the request. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - // Server sends a response with status OK. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // In principle, the server batch should complete before the client - // recv ops batch, but in the proxy fixtures, there are multiple threads - // involved, so the completion order tends to be a little racy. - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - // Make sure the "grpc-previous-rpc-attempts" header was NOT sent, since - // we don't do that for transparent retries. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} +namespace grpc_core { namespace { // A filter that, for the first call it sees, will fail all batches except @@ -258,16 +77,15 @@ class FailFirstCallFilter { if (calld->fail_) { if (batch->recv_trailing_metadata) { batch->payload->recv_trailing_metadata.recv_trailing_metadata->Set( - grpc_core::GrpcStreamNetworkState(), - grpc_core::GrpcStreamNetworkState::kNotSeenByServer); + GrpcStreamNetworkState(), + GrpcStreamNetworkState::kNotSeenByServer); } if (!batch->cancel_stream) { grpc_transport_stream_op_batch_finish_with_failure( batch, grpc_error_set_int( GRPC_ERROR_CREATE("FailFirstCallFilter failing batch"), - grpc_core::StatusIntProperty::kRpcStatus, - GRPC_STATUS_UNAVAILABLE), + StatusIntProperty::kRpcStatus, GRPC_STATUS_UNAVAILABLE), calld->call_combiner_); return; } @@ -279,7 +97,7 @@ class FailFirstCallFilter { explicit CallData(const grpc_call_element_args* args) : call_combiner_(args->call_combiner) {} - grpc_core::CallCombiner* call_combiner_; + CallCombiner* call_combiner_; bool fail_ = false; }; @@ -313,28 +131,74 @@ grpc_channel_filter FailFirstCallFilter::kFilterVtable = { "FailFirstCallFilter", }; -} // namespace - -void retry_transparent_goaway(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage( - GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY + 1, - [](grpc_core::ChannelStackBuilder* builder) { - // Skip on proxy (which explicitly disables retries). - if (!builder->channel_args() - .GetBool(GRPC_ARG_ENABLE_RETRIES) - .value_or(true)) { - return true; - } - // Install filter. - builder->PrependFilter(&FailFirstCallFilter::kFilterVtable); - return true; - }); - }, - [config] { test_retry_transparent_goaway(config); }); +// Tests transparent retries when the call was never sent out on the wire. +TEST_P(RetryTest, TransparentGoaway) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY + 1, + [](ChannelStackBuilder* builder) { + // Skip on proxy (which explicitly disables retries). + if (!builder->channel_args() + .GetBool(GRPC_ARG_ENABLE_RETRIES) + .value_or(true)) { + return true; + } + // Install filter. + builder->PrependFilter(&FailFirstCallFilter::kFilterVtable); + return true; + }); + }); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + // Start a batch containing send ops. + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); + // Start a batch containing recv ops. + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + // Client send ops should now complete. + Expect(1, true); + Step(); + // Server should get a call. + auto s = RequestCall(101); + Expect(101, true); + Step(); + // Server receives the request. + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); + // Server sends a response with status OK. + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendInitialMetadata({}) + .SendMessage("bar") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + // In principle, the server batch should complete before the client + // recv ops batch, but in the proxy fixtures, there are multiple threads + // involved, so the completion order tends to be a little racy. + Expect(103, true); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(server_message.payload(), "bar"); + EXPECT_EQ(client_message.payload(), "foo"); + // Make sure the "grpc-previous-rpc-attempts" header was NOT sent, since + // we don't do that for transparent retries. + EXPECT_EQ(s.GetInitialMetadata("grpc-previous-rpc-attempts"), absl::nullopt); } -void retry_transparent_goaway_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc b/test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc index e75e94865a0..9aa13006fe6 100644 --- a/test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc +++ b/test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc @@ -14,35 +14,18 @@ // limitations under the License. // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - const grpc_core::ChannelArgs& client_args, - const grpc_core::ChannelArgs& server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(client_args, server_args); - f->InitServer(server_args); - f->InitClient(client_args); - return f; -} +namespace grpc_core { +namespace { // Tests transparent retries when the call was never sent out on the wire. // This is similar to retry_transparent_not_sent_on_wire, except that // instead of simulating the response with a filter, we actually have @@ -52,273 +35,97 @@ static std::unique_ptr begin_test( // Then, before the first call finishes, the server is shut down and // restarted. The second call will fail in that transport instance and // will be transparently retried after the server starts up again. -static void test_retry_transparent_max_concurrent_streams( - const CoreTestConfiguration& config) { - grpc_op ops[6]; - grpc_op* op; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - grpc_call_error error; - - auto server_args = - grpc_core::ChannelArgs().Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1); - auto f = begin_test(config, "retry_transparent_max_concurrent_streams", - grpc_core::ChannelArgs(), server_args); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - - // Client starts a call. - grpc_call* c = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, deadline, - nullptr); - GPR_ASSERT(c); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array_init(&initial_metadata_recv); - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_status_code status; - grpc_slice details; - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - +TEST_P(RetryHttp2Test, RetryTransparentMaxConcurrentStreams) { + const auto server_args = + ChannelArgs().Set(GRPC_ARG_MAX_CONCURRENT_STREAMS, 1); + InitServer(server_args); + InitClient(ChannelArgs()); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); // Server should get a call. - grpc_call* s; - grpc_metadata_array request_metadata_recv; - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details call_details; - grpc_call_details_init(&call_details); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - grpc_call_details_destroy(&call_details); - grpc_metadata_array_destroy(&request_metadata_recv); - + auto s = RequestCall(101); + Expect(101, true); + Step(); + EXPECT_EQ(s.method(), "/service/method"); // Client starts a second call. // We set wait_for_ready for this call, so that if it retries before // the server comes back up, it stays pending. - grpc_call* c2 = grpc_channel_create_call( - f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq(), - grpc_slice_from_static_string("/service/method"), nullptr, deadline, - nullptr); - GPR_ASSERT(c2); - grpc_byte_buffer* request_payload2 = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_metadata_array initial_metadata_recv2; - grpc_metadata_array_init(&initial_metadata_recv2); - grpc_byte_buffer* response_payload_recv2 = nullptr; - grpc_metadata_array trailing_metadata_recv2; - grpc_metadata_array_init(&trailing_metadata_recv2); - grpc_status_code status2; - grpc_slice details2; - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload2; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = - &initial_metadata_recv2; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv2; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv2; - op->data.recv_status_on_client.status = &status2; - op->data.recv_status_on_client.status_details = &details2; - op++; - error = grpc_call_start_batch(c2, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + auto c2 = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + IncomingStatusOnClient server_status2; + IncomingMetadata server_initial_metadata2; + IncomingMessage server_message2; + c2.NewBatch(2) + .SendInitialMetadata({}, GRPC_INITIAL_METADATA_WAIT_FOR_READY) + .SendMessage("bar") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata2) + .RecvMessage(server_message2) + .RecvStatusOnClient(server_status2); // Start server shutdown. - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(102)); - + ShutdownServerAndNotify(102); // Server handles the first call. - grpc_byte_buffer* request_payload_recv = nullptr; - int was_cancelled = 2; - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMessage client_message; + s.NewBatch(103).RecvMessage(client_message); + IncomingCloseOnServer client_close; + s.NewBatch(104) + .RecvCloseOnServer(client_close) + .SendInitialMetadata({}) + .SendMessage("baz") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); // Server completes first call and shutdown. // Client completes first call. - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - + Expect(104, true); + Expect(103, true); + Expect(102, true); + Expect(1, true); + Step(); // Clean up from first call. - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - GPR_ASSERT(was_cancelled == 0); - grpc_byte_buffer_destroy(response_payload); - grpc_call_unref(s); - grpc_byte_buffer_destroy(request_payload); - grpc_metadata_array_destroy(&initial_metadata_recv); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - grpc_byte_buffer_destroy(response_payload_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - grpc_slice_unref(details); - grpc_call_unref(c); - + EXPECT_EQ(client_message.payload(), "foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(server_message.payload(), "baz"); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); // Destroy server and then restart it. - f->DestroyServer(); - f->InitServer(server_args); - + InitServer(server_args); // Server should get the second call. - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(201)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(201), true); - cqv.Verify(); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - grpc_call_details_destroy(&call_details); + auto s2 = RequestCall(201); + Expect(201, true); + Step(); + EXPECT_EQ(s2.method(), "/service/method"); // Make sure the "grpc-previous-rpc-attempts" header was NOT sent, since // we don't do that for transparent retries. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - grpc_metadata_array_destroy(&request_metadata_recv); - + EXPECT_EQ(s2.GetInitialMetadata("grpc-previous-rpc-attempts"), absl::nullopt); // Server handles the second call. - request_payload_recv = nullptr; - was_cancelled = 2; - grpc_byte_buffer* response_payload2 = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(202), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload2; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(203), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMessage client_message2; + IncomingCloseOnServer client_close2; + s2.NewBatch(202).RecvMessage(client_message2); + s2.NewBatch(203) + .RecvCloseOnServer(client_close2) + .SendInitialMetadata({}) + .SendMessage("qux") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); // Second call completes. - cqv.Expect(grpc_core::CqVerifier::tag(203), true); - cqv.Expect(grpc_core::CqVerifier::tag(202), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - + Expect(203, true); + Expect(202, true); + Expect(2, true); + Step(); // Clean up from second call. - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - grpc_byte_buffer_destroy(request_payload_recv); - GPR_ASSERT(was_cancelled == 0); - grpc_byte_buffer_destroy(response_payload2); - grpc_call_unref(s); - grpc_byte_buffer_destroy(request_payload2); - grpc_metadata_array_destroy(&initial_metadata_recv2); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv2, response_payload_slice)); - grpc_byte_buffer_destroy(response_payload_recv2); - grpc_metadata_array_destroy(&trailing_metadata_recv2); - GPR_ASSERT(status2 == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details2, "xyz")); - grpc_slice_unref(details2); - grpc_call_unref(c2); + EXPECT_EQ(client_message2.payload(), "bar"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(server_message2.payload(), "qux"); + EXPECT_EQ(server_status2.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status2.message(), "xyz"); } - -void retry_transparent_max_concurrent_streams( - const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_transparent_max_concurrent_streams(config); -} - -void retry_transparent_max_concurrent_streams_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc b/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc index b7c1a1f77b7..7b95bb0de97 100644 --- a/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc +++ b/test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc @@ -16,21 +16,14 @@ #include -#include -#include #include #include "absl/status/status.h" #include "absl/types/optional.h" +#include "gtest/gtest.h" -#include #include -#include -#include #include -#include -#include -#include #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_fwd.h" @@ -38,6 +31,7 @@ #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/error.h" @@ -45,184 +39,9 @@ #include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Tests transparent retries when the call was never sent out on the wire. -static void test_retry_transparent_not_sent_on_wire( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - auto f = begin_test(config, "retry_transparent_not_sent_on_wire", nullptr, - nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - - // Start a batch containing send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Start a batch containing recv ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // Client send ops should now complete. - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - // Server should get a call. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - // Server receives the request. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - // Server sends a response with status OK. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - op->data.send_status_from_server.status_details = &status_details; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - // In principle, the server batch should complete before the client - // recv ops batch, but in the proxy fixtures, there are multiple threads - // involved, so the completion order tends to be a little racy. - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - // Make sure the "grpc-previous-rpc-attempts" header was NOT sent, since - // we don't do that for transparent retries. - for (size_t i = 0; i < request_metadata_recv.count; ++i) { - GPR_ASSERT(!grpc_slice_eq( - request_metadata_recv.metadata[i].key, - grpc_slice_from_static_string("grpc-previous-rpc-attempts"))); - } - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); - - grpc_call_unref(c); - grpc_call_unref(s); -} +namespace grpc_core { namespace { // A filter that, for the first 10 calls it sees, will fail all batches except @@ -258,16 +77,14 @@ class FailFirstTenCallsFilter { if (calld->fail_) { if (batch->recv_trailing_metadata) { batch->payload->recv_trailing_metadata.recv_trailing_metadata->Set( - grpc_core::GrpcStreamNetworkState(), - grpc_core::GrpcStreamNetworkState::kNotSentOnWire); + GrpcStreamNetworkState(), GrpcStreamNetworkState::kNotSentOnWire); } if (!batch->cancel_stream) { grpc_transport_stream_op_batch_finish_with_failure( batch, grpc_error_set_int( GRPC_ERROR_CREATE("FailFirstTenCallsFilter failing batch"), - grpc_core::StatusIntProperty::kRpcStatus, - GRPC_STATUS_UNAVAILABLE), + StatusIntProperty::kRpcStatus, GRPC_STATUS_UNAVAILABLE), calld->call_combiner_); return; } @@ -279,7 +96,7 @@ class FailFirstTenCallsFilter { explicit CallData(const grpc_call_element_args* args) : call_combiner_(args->call_combiner) {} - grpc_core::CallCombiner* call_combiner_; + CallCombiner* call_combiner_; bool fail_ = false; }; @@ -313,28 +130,74 @@ grpc_channel_filter FailFirstTenCallsFilter::kFilterVtable = { "FailFirstTenCallsFilter", }; -} // namespace - -void retry_transparent_not_sent_on_wire(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - grpc_core::CoreConfiguration::RunWithSpecialConfiguration( - [](grpc_core::CoreConfiguration::Builder* builder) { - grpc_core::BuildCoreConfiguration(builder); - builder->channel_init()->RegisterStage( - GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY + 1, - [](grpc_core::ChannelStackBuilder* builder) { - // Skip on proxy (which explicitly disables retries). - if (!builder->channel_args() - .GetBool(GRPC_ARG_ENABLE_RETRIES) - .value_or(true)) { - return true; - } - // Install filter. - builder->PrependFilter(&FailFirstTenCallsFilter::kFilterVtable); - return true; - }); - }, - [config] { test_retry_transparent_not_sent_on_wire(config); }); +// Tests transparent retries when the call was never sent out on the wire. +TEST_P(RetryTest, RetryTransparentNotSentOnWire) { + CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) { + builder->channel_init()->RegisterStage( + GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY + 1, + [](ChannelStackBuilder* builder) { + // Skip on proxy (which explicitly disables retries). + if (!builder->channel_args() + .GetBool(GRPC_ARG_ENABLE_RETRIES) + .value_or(true)) { + return true; + } + // Install filter. + builder->PrependFilter(&FailFirstTenCallsFilter::kFilterVtable); + return true; + }); + }); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + // Start a batch containing send ops. + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); + // Start a batch containing recv ops. + IncomingStatusOnClient server_status; + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + // Client send ops should now complete. + Expect(1, true); + Step(); + // Server should get a call. + auto s = RequestCall(101); + Expect(101, true); + Step(); + // Server receives the request. + IncomingMessage client_message; + s.NewBatch(102).RecvMessage(client_message); + Expect(102, true); + Step(); + // Server sends a response with status OK. + IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendInitialMetadata({}) + .SendMessage("bar") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + // In principle, the server batch should complete before the client + // recv ops batch, but in the proxy fixtures, there are multiple threads + // involved, so the completion order tends to be a little racy. + Expect(103, true); + Expect(2, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(client_message.payload(), "foo"); + EXPECT_EQ(server_message.payload(), "bar"); + // Make sure the "grpc-previous-rpc-attempts" header was NOT sent, since + // we don't do that for transparent retries. + EXPECT_EQ(s.GetInitialMetadata("grpc-previous-rpc-attempts"), absl::nullopt); } -void retry_transparent_not_sent_on_wire_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_unref_before_finish.cc b/test/core/end2end/tests/retry_unref_before_finish.cc index 7216ff1b2f6..f2782d8b5bb 100644 --- a/test/core/end2end/tests/retry_unref_before_finish.cc +++ b/test/core/end2end/tests/retry_unref_before_finish.cc @@ -14,183 +14,70 @@ // limitations under the License. // -#include +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we can unref a call whose status is cached but not yet // requested by the application. This should not cause a memory leak. -static void test_retry_unref_before_finish( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_error error; - int was_cancelled = 2; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = - begin_test(config, "retry_unref_before_finish", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - +TEST_P(RetryTest, RetryUnrefBeforeFinish) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + auto c = + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create(); // Client starts send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); // Client starts recv_initial_metadata and recv_message, but not // recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c.NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); // Server gets a call and client send ops complete. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + auto s = RequestCall(101); + Expect(1, true); + Expect(101, true); + Step(); // Server immediately sends FAILED_PRECONDITION status (not retriable). // This forces the retry filter to start a recv_trailing_metadata op // internally, since the application hasn't started it yet. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_FAILED_PRECONDITION; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_FAILED_PRECONDITION, "xyz", {}) + .RecvCloseOnServer(client_close); // Server ops complete and client recv ops complete. - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); - GPR_ASSERT(was_cancelled == 0); - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - // Client unrefs the call without starting recv_trailing_metadata. - // This should trigger a cancellation. - grpc_call_unref(c); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -void retry_unref_before_finish(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_unref_before_finish(config); + Expect(2, true); + Expect(102, true); + Step(); + EXPECT_EQ(s.method(), "/service/method"); + EXPECT_FALSE(client_close.was_cancelled()); } - -void retry_unref_before_finish_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/retry_unref_before_recv.cc b/test/core/end2end/tests/retry_unref_before_recv.cc index 7daacec288d..0251c3a816d 100644 --- a/test/core/end2end/tests/retry_unref_before_recv.cc +++ b/test/core/end2end/tests/retry_unref_before_recv.cc @@ -14,184 +14,81 @@ // limitations under the License. // -#include +#include "absl/types/optional.h" +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/useful.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Tests that we can unref a call while recv ops are started but before // they complete. This ensures that we don't drop callbacks or cause a // memory leak. -static void test_retry_unref_before_recv(const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); - grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_error error; - int was_cancelled = 2; - - grpc_arg args[] = { - grpc_channel_arg_string_create( - const_cast(GRPC_ARG_SERVICE_CONFIG), - const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}")), - }; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; - auto f = begin_test(config, "retry_unref_before_recv", &client_args, nullptr); - - grpc_core::CqVerifier cqv(f->cq()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), - grpc_slice_from_static_string("/service/method"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - grpc_slice status_details = grpc_slice_from_static_string("xyz"); +TEST_P(RetryTest, UnrefBeforeRecv) { + InitServer(ChannelArgs()); + InitClient(ChannelArgs().Set( + GRPC_ARG_SERVICE_CONFIG, + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + absl::optional c{ + NewClientCall("/service/method").Timeout(Duration::Seconds(5)).Create()}; // Client starts send ops. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c->NewBatch(1) + .SendInitialMetadata({}) + .SendMessage("foo") + .SendCloseFromClient(); // Client starts recv_initial_metadata and recv_message, but not // recv_trailing_metadata. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingMetadata server_initial_metadata; + IncomingMessage server_message; + c->NewBatch(2) + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message); // Server gets a call and client send ops complete. - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - + auto s = RequestCall(101); + Expect(1, true); + Expect(101, true); + Step(); // Client unrefs the call without starting recv_trailing_metadata. // This should trigger a cancellation. - grpc_call_unref(c); - + c.reset(); // Server immediately sends FAILED_PRECONDITION status (not retriable). // This forces the retry filter to start a recv_trailing_metadata op // internally, since the application hasn't started it yet. - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_FAILED_PRECONDITION; - op->data.send_status_from_server.status_details = &status_details; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_FAILED_PRECONDITION, "xyz", {}) + .RecvCloseOnServer(client_close); // Server ops complete and client recv ops complete. - cqv.Expect(grpc_core::CqVerifier::tag(2), false); // Failure! - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); + Expect(2, false); // Failure! + Expect(102, true); + Step(); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); + EXPECT_EQ(s.method(), "/service/method"); // Note: Not checking the value of was_cancelled here, because it will // be flaky, depending on whether the server sent its response before // the client sent its cancellation. - - grpc_call_unref(s); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_call_details_init(&call_details); - - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - -void retry_unref_before_recv(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); - test_retry_unref_before_recv(config); } -void retry_unref_before_recv_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/server_finishes_request.cc b/test/core/end2end/tests/server_finishes_request.cc index d12a7329448..b0568071418 100644 --- a/test/core/end2end/tests/server_finishes_request.cc +++ b/test/core/end2end/tests/server_finishes_request.cc @@ -16,141 +16,46 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void simple_request_body(const CoreTestConfiguration& /*config*/, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); +namespace grpc_core { +namespace { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(CoreEnd2endTest, ServerFinishesRequest) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); + auto s = RequestCall(101); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); + Expect(101, true); + Step(); - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}) + .RecvCloseOnServer(client_close); - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - simple_request_body(config, f.get()); -} + Expect(102, true); + Expect(1, true); + Step(); -void server_finishes_request(const CoreTestConfiguration& config) { - test_invoke_simple_request(config); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -void server_finishes_request_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/server_streaming.cc b/test/core/end2end/tests/server_streaming.cc index 80e1e8a6d25..7367cc5b457 100644 --- a/test/core/end2end/tests/server_streaming.cc +++ b/test/core/end2end/tests/server_streaming.cc @@ -16,228 +16,86 @@ // // -#include +#include "gtest/gtest.h" -#include -#include -#include - -#include -#include -#include -#include #include #include -#include -#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args, - int num_messages) { - gpr_log(GPR_INFO, "%s\nRunning test: %s/%s/%d", std::string(100, '*').c_str(), - test_name, config.name, num_messages); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Client requests status along with the initial metadata. Server streams // messages and ends with a non-OK status. Client reads after server is done // writing, and expects to get the status after the messages. -static void test_server_streaming(const CoreTestConfiguration& config, - int num_messages) { - auto f = begin_test(config, "test_server_streaming", nullptr, nullptr, - num_messages); - grpc_call* c; - grpc_call* s; - auto cqv = std::make_unique(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - grpc_byte_buffer* request_payload_recv; - grpc_byte_buffer* response_payload; - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello world"); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - // Client requests status early but should not receive status till all the - // messages are received. - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - +void ServerStreaming(CoreEnd2endTest& test, int num_messages) { + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .RecvInitialMetadata(server_initial_metadata) + // Client requests status early but should not receive status till all the + // messages are received. + .RecvStatusOnClient(server_status); // Client sends close early - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv->Expect(grpc_core::CqVerifier::tag(3), true); - cqv->Verify(); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(100)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv->Expect(grpc_core::CqVerifier::tag(100), true); - cqv->Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(101), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv->Expect(grpc_core::CqVerifier::tag(101), true); - cqv->Verify(); - + c.NewBatch(3).SendCloseFromClient(); + test.Expect(3, true); + test.Step(); + auto s = test.RequestCall(100); + test.Expect(100, true); + test.Step(); + s.NewBatch(101).SendInitialMetadata({}); + test.Expect(101, true); + test.Step(); // Server writes bunch of messages for (int i = 0; i < num_messages; i++) { - response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv->Expect(grpc_core::CqVerifier::tag(103), true); - cqv->Verify(); - - grpc_byte_buffer_destroy(response_payload); + s.NewBatch(103).SendMessage("hello world"); + test.Expect(103, true); + test.Step(); } - // Server sends status - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(104) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); bool seen_status = false; - cqv->Expect(grpc_core::CqVerifier::tag(1), - grpc_core::CqVerifier::Maybe{&seen_status}); - cqv->Expect(grpc_core::CqVerifier::tag(104), true); - cqv->Verify(); + test.Expect(1, CoreEnd2endTest::Maybe{&seen_status}); + test.Expect(104, true); + test.Step(); // Client keeps reading messages till it gets the status int num_messages_received = 0; while (true) { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv->Expect(grpc_core::CqVerifier::tag(1), - grpc_core::CqVerifier::Maybe{&seen_status}); - cqv->Expect(grpc_core::CqVerifier::tag(102), true); - cqv->Verify(); - if (request_payload_recv == nullptr) { + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(102).RecvMessage(server_message); + test.Expect(1, CqVerifier::Maybe{&seen_status}); + test.Expect(102, true); + test.Step(); + if (server_message.is_end_of_stream()) { // The transport has received the trailing metadata. break; } - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - grpc_byte_buffer_destroy(request_payload_recv); + EXPECT_EQ(server_message.payload(), "hello world"); num_messages_received++; } GPR_ASSERT(num_messages_received == num_messages); if (!seen_status) { - cqv->Expect(grpc_core::CqVerifier::tag(1), true); - cqv->Verify(); + test.Expect(1, true); + test.Step(); } - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - - grpc_slice_unref(response_payload_slice); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); +} - grpc_call_unref(c); - grpc_call_unref(s); +TEST_P(Http2Test, ServerStreaming) { ServerStreaming(*this, 1); } - cqv.reset(); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - grpc_slice_unref(details); -} +TEST_P(Http2Test, ServerStreamingEmptyStream) { ServerStreaming(*this, 0); } -void server_streaming(const CoreTestConfiguration& config) { - test_server_streaming(config, 0); - test_server_streaming(config, 1); - test_server_streaming(config, 10); -} +TEST_P(Http2Test, ServerStreaming10Messages) { ServerStreaming(*this, 10); } -void server_streaming_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/shutdown_finishes_calls.cc b/test/core/end2end/tests/shutdown_finishes_calls.cc index 4d3e80a50b4..eb06c915684 100644 --- a/test/core/end2end/tests/shutdown_finishes_calls.cc +++ b/test/core/end2end/tests/shutdown_finishes_calls.cc @@ -16,109 +16,32 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include #include -#include #include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" #include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void test_early_server_shutdown_finishes_inflight_calls( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - auto f = - begin_test(config, "test_early_server_shutdown_finishes_inflight_calls", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->data.send_initial_metadata.metadata = nullptr; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +namespace grpc_core { +namespace { + +TEST_P(CoreEnd2endTest, EarlyServerShutdownFinishesInflightCalls) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102).RecvCloseOnServer(client_close); // Make sure we don't shutdown the server while HTTP/2 PING frames are still // being exchanged on the newly established connection. It can lead to @@ -128,33 +51,20 @@ static void test_early_server_shutdown_finishes_inflight_calls( gpr_sleep_until(grpc_timeout_seconds_to_deadline(1)); // shutdown and destroy the server - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(1000)); - grpc_server_cancel_all_calls(f->server()); - - cqv.Expect(grpc_core::CqVerifier::tag(1000), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); + ShutdownServerAndNotify(1000); + CancelAllCallsOnServer(); - f->DestroyServer(); + Expect(1000, true); + Expect(102, true); + Expect(1, true); + Step(); - GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} + DestroyServer(); -void shutdown_finishes_calls(const CoreTestConfiguration& config) { - test_early_server_shutdown_finishes_inflight_calls(config); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_TRUE(client_close.was_cancelled()); } -void shutdown_finishes_calls_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/shutdown_finishes_tags.cc b/test/core/end2end/tests/shutdown_finishes_tags.cc index f774759978b..c9781e36b01 100644 --- a/test/core/end2end/tests/shutdown_finishes_tags.cc +++ b/test/core/end2end/tests/shutdown_finishes_tags.cc @@ -16,56 +16,23 @@ // // -#include -#include +#include "gtest/gtest.h" -#include -#include - -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" #include "test/core/end2end/end2end_tests.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -static void test_early_server_shutdown_finishes_tags( - const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_early_server_shutdown_finishes_tags", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_call* s = reinterpret_cast(1); - grpc_call_details call_details; - grpc_metadata_array request_metadata_recv; - - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); +namespace grpc_core { +namespace { +TEST_P(CoreEnd2endTest, ShutdownFinishesTags) { // upon shutdown, the server should finish all requested calls indicating // no new call - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - f->ShutdownClient(); - grpc_server_shutdown_and_notify(f->server(), f->cq(), - grpc_core::CqVerifier::tag(1000)); - cqv.Expect(grpc_core::CqVerifier::tag(101), false); - cqv.Expect(grpc_core::CqVerifier::tag(1000), true); - cqv.Verify(); - GPR_ASSERT(s == nullptr); -} - -void shutdown_finishes_tags(const CoreTestConfiguration& config) { - test_early_server_shutdown_finishes_tags(config); + auto s = RequestCall(101); + ShutdownAndDestroyClient(); + ShutdownServerAndNotify(1000); + Expect(101, false); + Expect(1000, true); + Step(); } -void shutdown_finishes_tags_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/simple_delayed_request.cc b/test/core/end2end/tests/simple_delayed_request.cc index a5e307c6ffc..3e1719df50b 100644 --- a/test/core/end2end/tests/simple_delayed_request.cc +++ b/test/core/end2end/tests/simple_delayed_request.cc @@ -16,164 +16,48 @@ // // -#include - -#include -#include +#include "gtest/gtest.h" #include -#include -#include #include -#include -#include #include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static void simple_delayed_request_body(CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - f->InitClient(grpc_core::ChannelArgs()); - f->InitServer(grpc_core::ChannelArgs()); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); -} - -static void test_simple_delayed_request_short( - const CoreTestConfiguration& config) { - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000) - .ToC(); - gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_short", - config.name); - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - - simple_delayed_request_body(f.get()); -} - -static void test_simple_delayed_request_long( - const CoreTestConfiguration& config) { - auto client_args = grpc_core::ChannelArgs() - .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) - .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000) - .ToC(); - - gpr_log(GPR_INFO, "Running test: %s/%s", "test_simple_delayed_request_long", - config.name); - auto f = - config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); - // This timeout should be longer than a single retry - simple_delayed_request_body(f.get()); -} -void simple_delayed_request(const CoreTestConfiguration& config) { - GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION); - test_simple_delayed_request_short(config); - test_simple_delayed_request_long(config); +namespace grpc_core { +namespace { + +TEST_P(CoreClientChannelTest, SimpleDelayedRequestShort) { + InitClient(ChannelArgs() + .Set(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000) + .Set(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 1000) + .Set(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 5000)); + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + IncomingMetadata server_initial_metadata; + IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}, GRPC_INITIAL_METADATA_WAIT_FOR_READY) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + InitServer(ChannelArgs()); + auto s = RequestCall(101); + Expect(101, true); + Step(); + IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + Expect(102, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); } -void simple_delayed_request_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/simple_metadata.cc b/test/core/end2end/tests/simple_metadata.cc index 79c3da0d391..4574d7c7caa 100644 --- a/test/core/end2end/tests/simple_metadata.cc +++ b/test/core/end2end/tests/simple_metadata.cc @@ -16,208 +16,59 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Request/response with metadata and payload. -static void test_request_response_with_metadata_and_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), - grpc_slice_from_static_string("val3"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key4"), - grpc_slice_from_static_string("val4"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - auto f = begin_test(config, "test_request_response_with_metadata_and_payload", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} -void simple_metadata(const CoreTestConfiguration& config) { - test_request_response_with_metadata_and_payload(config); +namespace grpc_core { +namespace { + +TEST_P(CoreEnd2endTest, SimpleMetadata) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({{"key1", "val1"}, {"key2", "val2"}}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102) + .SendInitialMetadata({{"key3", "val3"}, {"key4", "val4"}}) + .RecvMessage(client_message); + Expect(102, true); + Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage("hello you") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", + {{"key5", "val5"}, {"key6", "val6"}}); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(server_message.payload(), "hello you"); + EXPECT_EQ(client_message.payload(), "hello world"); + EXPECT_EQ(s.GetInitialMetadata("key1"), "val1"); + EXPECT_EQ(s.GetInitialMetadata("key2"), "val2"); + EXPECT_EQ(server_initial_metadata.Get("key3"), "val3"); + EXPECT_EQ(server_initial_metadata.Get("key4"), "val4"); + EXPECT_EQ(server_status.GetTrailingMetadata("key5"), "val5"); + EXPECT_EQ(server_status.GetTrailingMetadata("key6"), "val6"); } -void simple_metadata_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc index 2a236ceede1..501cf397e68 100644 --- a/test/core/end2end/tests/simple_request.cc +++ b/test/core/end2end/tests/simple_request.cc @@ -17,218 +17,93 @@ // #include -#include #include -#include #include #include -#include -#include -#include +#include "absl/strings/match.h" +#include "absl/types/optional.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + #include -#include #include -#include -#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/stats_data.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "%s", std::string(100, '*').c_str()); - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +using testing::HasSubstr; +using testing::StartsWith; -static void check_peer(char* peer_name) { +namespace grpc_core { +namespace { +void CheckPeer(std::string peer_name) { // If the peer name is a uds path, then check if it is filled - if (strncmp(peer_name, "unix:/", strlen("unix:/")) == 0) { - GPR_ASSERT(strncmp(peer_name, "unix:/tmp/grpc_fullstack_test.", - strlen("unix:/tmp/grpc_fullstack_test.")) == 0); + if (absl::StartsWith(peer_name, "unix:/")) { + EXPECT_THAT(peer_name, StartsWith("unix:/tmp/grpc_fullstack_test.")); } } -static void simple_request_body(const CoreTestConfiguration& config, - CoreTestFixture* f) { - grpc_call* c; - grpc_call* s; - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_call_details call_details; - grpc_status_code status; - const char* error_string; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - char* peer; - - auto before = grpc_core::global_stats().Collect(); - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); - gpr_free(peer); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->data.recv_status_on_client.error_string = &error_string; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - peer = grpc_call_get_peer(s); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "server_peer=%s", peer); - check_peer(peer); - gpr_free(peer); - peer = grpc_call_get_peer(c); - GPR_ASSERT(peer != nullptr); - gpr_log(GPR_DEBUG, "client_peer=%s", peer); - check_peer(peer); - gpr_free(peer); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); +void SimpleRequestBody(CoreEnd2endTest& test) { + auto before = global_stats().Collect(); + auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = test.RequestCall(101); + test.Expect(101, true); + test.Step(); + EXPECT_NE(s.GetPeer(), absl::nullopt); + CheckPeer(*s.GetPeer()); + EXPECT_NE(c.GetPeer(), absl::nullopt); + CheckPeer(*c.GetPeer()); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(102) + .SendInitialMetadata({}) + .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {}) + .RecvCloseOnServer(client_close); + test.Expect(102, true); + test.Expect(1, true); + test.Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED); + EXPECT_EQ(server_status.message(), "xyz"); // the following sanity check makes sure that the requested error string is // correctly populated by the core. It looks for certain substrings that are // not likely to change much. Some parts of the error, like time created, // obviously are not checked. - GPR_ASSERT(nullptr != strstr(error_string, "xyz")); - GPR_ASSERT(nullptr != strstr(error_string, "Error received from peer")); - GPR_ASSERT(nullptr != strstr(error_string, "grpc_message")); - GPR_ASSERT(nullptr != strstr(error_string, "grpc_status")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - - grpc_slice_unref(details); - gpr_free(const_cast(error_string)); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - + EXPECT_THAT(server_status.error_string(), HasSubstr("xyz")); + EXPECT_THAT(server_status.error_string(), + HasSubstr("Error received from peer")); + EXPECT_THAT(server_status.error_string(), HasSubstr("grpc_message")); + EXPECT_THAT(server_status.error_string(), HasSubstr("grpc_status")); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); uint64_t expected_calls = 1; - if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { + if (test.GetParam()->feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) { expected_calls *= 2; } - - auto after = grpc_core::global_stats().Collect(); - - gpr_log(GPR_DEBUG, "%s", grpc_core::StatsAsJson(after.get()).c_str()); - - GPR_ASSERT(after->client_calls_created - before->client_calls_created == - expected_calls); - GPR_ASSERT(after->server_calls_created - before->server_calls_created == - expected_calls); + auto after = global_stats().Collect(); + gpr_log(GPR_DEBUG, "%s", StatsAsJson(after.get()).c_str()); + EXPECT_EQ(after->client_calls_created - before->client_calls_created, + expected_calls); + EXPECT_EQ(after->server_calls_created - before->server_calls_created, + expected_calls); } -static void test_invoke_simple_request(const CoreTestConfiguration& config) { - auto f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr); - simple_request_body(config, f.get()); -} +TEST_P(CoreEnd2endTest, SimpleRequest) { SimpleRequestBody(*this); } -static void test_invoke_10_simple_requests( - const CoreTestConfiguration& config) { - int i; - auto f = - begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr); - for (i = 0; i < 10; i++) { - simple_request_body(config, f.get()); - gpr_log(GPR_INFO, "Running test: Passed simple request %d", i); +TEST_P(CoreEnd2endTest, SimpleRequest10) { + for (int i = 0; i < 10; i++) { + SimpleRequestBody(*this); } } - -void simple_request(const CoreTestConfiguration& config) { - int i; - for (i = 0; i < 10; i++) { - test_invoke_simple_request(config); - } - test_invoke_10_simple_requests(config); -} - -void simple_request_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/streaming_error_response.cc b/test/core/end2end/tests/streaming_error_response.cc index 82f9a380801..347eede099d 100644 --- a/test/core/end2end/tests/streaming_error_response.cc +++ b/test/core/end2end/tests/streaming_error_response.cc @@ -19,234 +19,135 @@ /// \file Verify that status ordering rules are obeyed. /// \ref doc/status_ordering.md -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args, - bool request_status_early) { - gpr_log(GPR_INFO, "Running test: %s/%s/request_status_early=%s", test_name, - config.name, request_status_early ? "true" : "false"); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { +namespace { // Client sends a request with payload, potentially requesting status early. The // server reads and streams responses. The client cancels the RPC to get an // error status. (Server sending a non-OK status is not considered an error // status.) -static void test(const CoreTestConfiguration& config, bool request_status_early, - bool recv_message_separately) { - grpc_call* c; - grpc_call* s; - grpc_slice response_payload1_slice = grpc_slice_from_copied_string("hello"); - grpc_byte_buffer* response_payload1 = - grpc_raw_byte_buffer_create(&response_payload1_slice, 1); - grpc_slice response_payload2_slice = grpc_slice_from_copied_string("world"); - grpc_byte_buffer* response_payload2 = - grpc_raw_byte_buffer_create(&response_payload2_slice, 1); - auto f = begin_test(config, "streaming_error_response", nullptr, nullptr, - request_status_early); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* response_payload1_recv = nullptr; - grpc_byte_buffer* response_payload2_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status = GRPC_STATUS_OK; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - GPR_ASSERT(!recv_message_separately || request_status_early); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op++; - if (!recv_message_separately) { - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload1_recv; - op++; - } - if (request_status_early) { - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - } - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload1; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - if (recv_message_separately) { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload1_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - } - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - if (!request_status_early) { - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - } - if (recv_message_separately) { - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - } - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload2; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(CoreEnd2endTest, StreamingErrorResponse) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage response_payload1_recv; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(response_payload1_recv); + auto s = RequestCall(101); + Expect(101, true); + Step(); + s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello"); + Expect(102, true); + Expect(1, true); + Step(); + s.NewBatch(103).SendMessage("world"); // The success of the op depends on whether the payload is written before the // transport sees the end of stream. If the stream has been write closed // before the write completes, it would fail, otherwise it would succeed. // Since this behavior is dependent on the transport implementation, we allow // any success status with this op. - cqv.Expect(grpc_core::CqVerifier::tag(103), - grpc_core::CqVerifier::AnyStatus()); - - if (!request_status_early) { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload2_recv; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Verify(); - - GPR_ASSERT(response_payload2_recv != nullptr); - } - + Expect(103, AnyStatus()); + CoreEnd2endTest::IncomingMessage response_payload2_recv; + c.NewBatch(2).RecvMessage(response_payload2_recv); + Expect(2, true); + Step(); + EXPECT_FALSE(response_payload2_recv.is_end_of_stream()); // Cancel the call so that the client sets up an error status. - grpc_call_cancel(c, nullptr); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - if (request_status_early) { - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - } - cqv.Verify(); - - if (!request_status_early) { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Verify(); - - GPR_ASSERT(response_payload1_recv != nullptr); - GPR_ASSERT(response_payload2_recv != nullptr); - } - - GPR_ASSERT(status == GRPC_STATUS_CANCELLED); - GPR_ASSERT(was_cancelled == 1); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); + c.Cancel(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(104).RecvCloseOnServer(client_close); + Expect(104, true); + Step(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(3).RecvStatusOnClient(server_status); + Expect(3, true); + Step(); + EXPECT_FALSE(response_payload1_recv.is_end_of_stream()); + EXPECT_FALSE(response_payload2_recv.is_end_of_stream()); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); + EXPECT_TRUE(client_close.was_cancelled()); +} - grpc_byte_buffer_destroy(response_payload1); - grpc_byte_buffer_destroy(response_payload2); - grpc_byte_buffer_destroy(response_payload1_recv); - grpc_byte_buffer_destroy(response_payload2_recv); +TEST_P(CoreEnd2endTest, StreamingErrorResponseRequestStatusEarly) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage response_payload1_recv; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(response_payload1_recv) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello"); + Expect(102, true); + Step(); + s.NewBatch(103).SendMessage("world"); + // The success of the op depends on whether the payload is written before the + // transport sees the end of stream. If the stream has been write closed + // before the write completes, it would fail, otherwise it would succeed. + // Since this behavior is dependent on the transport implementation, we allow + // any success status with this op. + Expect(103, AnyStatus()); + // Cancel the call so that the client sets up an error status. + c.Cancel(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(104).RecvCloseOnServer(client_close); + Expect(104, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); + EXPECT_TRUE(client_close.was_cancelled()); } -void streaming_error_response(const CoreTestConfiguration& config) { - test(config, false, false); - test(config, true, false); - test(config, true, true); +TEST_P(CoreEnd2endTest, + StreamingErrorResponseRequestStatusEarlyAndRecvMessageSeparately) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(1) + .SendInitialMetadata({}) + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + s.NewBatch(102).SendInitialMetadata({}).SendMessage("hello"); + CoreEnd2endTest::IncomingMessage response_payload1_recv; + c.NewBatch(4).RecvMessage(response_payload1_recv); + Expect(102, true); + Expect(4, true); + Step(); + s.NewBatch(103).SendMessage("world"); + // The success of the op depends on whether the payload is written before the + // transport sees the end of stream. If the stream has been write closed + // before the write completes, it would fail, otherwise it would succeed. + // Since this behavior is dependent on the transport implementation, we allow + // any success status with this op. + Expect(103, AnyStatus()); + // Cancel the call so that the client sets up an error status. + c.Cancel(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(104).RecvCloseOnServer(client_close); + Expect(104, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED); + EXPECT_TRUE(client_close.was_cancelled()); } -void streaming_error_response_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/trailing_metadata.cc b/test/core/end2end/tests/trailing_metadata.cc index 55a1e0652c6..16b942cb98b 100644 --- a/test/core/end2end/tests/trailing_metadata.cc +++ b/test/core/end2end/tests/trailing_metadata.cc @@ -16,216 +16,57 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include -#include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Request/response with metadata and payload. -static void test_request_response_with_metadata_and_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_slice response_payload_slice = - grpc_slice_from_copied_string("hello you"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), - grpc_slice_from_static_string("val1"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key2"), - grpc_slice_from_static_string("val2"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key3"), - grpc_slice_from_static_string("val3"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key4"), - grpc_slice_from_static_string("val4"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - grpc_metadata meta_t[2] = {{grpc_slice_from_static_string("key5"), - grpc_slice_from_static_string("val5"), - {{nullptr, nullptr, nullptr, nullptr}}}, - {grpc_slice_from_static_string("key6"), - grpc_slice_from_static_string("val6"), - {{nullptr, nullptr, nullptr, nullptr}}}}; - auto f = begin_test(config, "test_request_response_with_metadata_and_payload", - nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_c; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 2; - op->data.send_initial_metadata.metadata = meta_s; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 2; - op->data.send_status_from_server.trailing_metadata = meta_t; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1")); - GPR_ASSERT(contains_metadata(&request_metadata_recv, "key2", "val2")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key3", "val3")); - GPR_ASSERT(contains_metadata(&initial_metadata_recv, "key4", "val4")); - GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key5", "val5")); - GPR_ASSERT(contains_metadata(&trailing_metadata_recv, "key6", "val6")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} -void trailing_metadata(const CoreTestConfiguration& config) { - test_request_response_with_metadata_and_payload(config); +namespace grpc_core { +namespace { + +TEST_P(CoreEnd2endTest, TrailingMetadata) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + CoreEnd2endTest::IncomingStatusOnClient server_status; + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + CoreEnd2endTest::IncomingMessage server_message; + c.NewBatch(1) + .SendInitialMetadata({{"key1", "val1"}, {"key2", "val2"}}) + .SendMessage("hello world") + .SendCloseFromClient() + .RecvInitialMetadata(server_initial_metadata) + .RecvMessage(server_message) + .RecvStatusOnClient(server_status); + auto s = RequestCall(101); + Expect(101, true); + Step(); + CoreEnd2endTest::IncomingMessage client_message; + s.NewBatch(102) + .SendInitialMetadata({{"key3", "val3"}, {"key4", "val4"}}) + .RecvMessage(client_message); + Expect(102, true); + Step(); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(103) + .RecvCloseOnServer(client_close) + .SendMessage("hello you") + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", + {{"key5", "val5"}, {"key6", "val6"}}); + Expect(103, true); + Expect(1, true); + Step(); + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(client_message.payload(), "hello world"); + EXPECT_EQ(server_message.payload(), "hello you"); + EXPECT_EQ(s.GetInitialMetadata("key1"), "val1"); + EXPECT_EQ(s.GetInitialMetadata("key2"), "val2"); + EXPECT_EQ(server_initial_metadata.Get("key3"), "val3"); + EXPECT_EQ(server_initial_metadata.Get("key4"), "val4"); + EXPECT_EQ(server_status.GetTrailingMetadata("key5"), "val5"); + EXPECT_EQ(server_status.GetTrailingMetadata("key6"), "val6"); } -void trailing_metadata_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/end2end/tests/write_buffering.cc b/test/core/end2end/tests/write_buffering.cc index 9dde20ba137..c6cdc8cf117 100644 --- a/test/core/end2end/tests/write_buffering.cc +++ b/test/core/end2end/tests/write_buffering.cc @@ -16,228 +16,66 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} +namespace grpc_core { // Client sends a request with payload, server reads then returns status. -static void test_invoke_request_with_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice1 = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload1 = - grpc_raw_byte_buffer_create(&request_payload_slice1, 1); - grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); - grpc_byte_buffer* request_payload2 = - grpc_raw_byte_buffer_create(&request_payload_slice2, 1); - auto f = - begin_test(config, "test_invoke_request_with_payload", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv1 = nullptr; - grpc_byte_buffer* request_payload_recv2 = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); // send message is buffered - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload1; - op->flags = GRPC_WRITE_BUFFER_HINT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(WriteBufferingTest, WriteBufferingWorks) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + c.NewBatch(1).SendInitialMetadata({}); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(2).RecvInitialMetadata(server_initial_metadata); + auto s = RequestCall(101); + Expect(1, true); // send message is buffered + Expect(101, true); + Step(); + c.NewBatch(3).SendMessage("hello world", GRPC_WRITE_BUFFER_HINT); + s.NewBatch(102).SendInitialMetadata({}); // recv message should not succeed yet - it's buffered at the client still - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv1; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); + CoreEnd2endTest::IncomingMessage request_payload_recv1; + s.NewBatch(103).RecvMessage(request_payload_recv1); + Expect(2, true); + Expect(3, true); + Expect(102, true); + Step(); // send another message, this time not buffered - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload2; - op->flags = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(4).SendMessage("abc123"); // now the first send should match up with the first recv - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); + Expect(103, true); + Expect(4, true); + Step(); // and the next recv should be ready immediately also - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv2; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(105), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(105), true); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload1); - grpc_byte_buffer_destroy(request_payload_recv1); - grpc_byte_buffer_destroy(request_payload2); - grpc_byte_buffer_destroy(request_payload_recv2); + CoreEnd2endTest::IncomingMessage request_payload_recv2; + s.NewBatch(104).RecvMessage(request_payload_recv2); + Expect(104, true); + Step(); + + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(5).SendCloseFromClient().RecvStatusOnClient(server_status); + + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(105) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + + Expect(105, true); + Expect(5, true); + Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(request_payload_recv1.payload(), "hello world"); + EXPECT_EQ(request_payload_recv2.payload(), "abc123"); } - -void write_buffering(const CoreTestConfiguration& config) { - test_invoke_request_with_payload(config); -} - -void write_buffering_pre_init(void) {} +} // namespace grpc_core diff --git a/test/core/end2end/tests/write_buffering_at_end.cc b/test/core/end2end/tests/write_buffering_at_end.cc index db4a1439a08..354eee04dd2 100644 --- a/test/core/end2end/tests/write_buffering_at_end.cc +++ b/test/core/end2end/tests/write_buffering_at_end.cc @@ -16,217 +16,67 @@ // // -#include +#include "gtest/gtest.h" -#include -#include - -#include #include -#include -#include #include -#include -#include -#include "src/core/lib/channel/channel_args.h" -#include "test/core/end2end/cq_verifier.h" +#include "src/core/lib/gprpp/time.h" #include "test/core/end2end/end2end_tests.h" -#include "test/core/util/test_config.h" - -static std::unique_ptr begin_test( - const CoreTestConfiguration& config, const char* test_name, - grpc_channel_args* client_args, grpc_channel_args* server_args) { - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), - grpc_core::ChannelArgs::FromC(server_args)); - f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); - f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); - return f; -} - -// Client sends a request with payload, server reads then returns status. -static void test_invoke_request_with_payload( - const CoreTestConfiguration& config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - auto f = - begin_test(config, "test_invoke_request_with_payload", nullptr, nullptr); - grpc_core::CqVerifier cqv(f->cq()); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv1 = nullptr; - grpc_byte_buffer* request_payload_recv2 = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details = grpc_empty_slice(); - int was_cancelled = 2; - - gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); - c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, - f->cq(), grpc_slice_from_static_string("/foo"), - nullptr, deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(1), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +namespace grpc_core { +namespace { - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(2), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); +TEST_P(WriteBufferingTest, WriteBufferingAtEnd) { + auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create(); + c.NewBatch(1).SendInitialMetadata({}); + CoreEnd2endTest::IncomingMetadata server_initial_metadata; + c.NewBatch(2).RecvInitialMetadata(server_initial_metadata); - GPR_ASSERT(GRPC_CALL_OK == - grpc_server_request_call(f->server(), &s, &call_details, - &request_metadata_recv, f->cq(), f->cq(), - grpc_core::CqVerifier::tag(101))); - cqv.Expect(grpc_core::CqVerifier::tag(1), true); // send message is buffered - cqv.Expect(grpc_core::CqVerifier::tag(101), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = GRPC_WRITE_BUFFER_HINT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(3), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(102), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); + auto s = RequestCall(101); + Expect(1, true); // send message is buffered + Expect(101, true); + Step(); + c.NewBatch(3).SendMessage("hello world", GRPC_WRITE_BUFFER_HINT); + s.NewBatch(102).SendInitialMetadata({}); // recv message should not succeed yet - it's buffered at the client still - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv1; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(103), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(2), true); - cqv.Expect(grpc_core::CqVerifier::tag(3), true); - cqv.Expect(grpc_core::CqVerifier::tag(102), true); - cqv.Verify(); + CoreEnd2endTest::IncomingMessage request_payload_recv1; + s.NewBatch(103).RecvMessage(request_payload_recv1); + Expect(2, true); + Expect(3, true); + Expect(102, true); + Step(); // send end of stream: should release the buffering - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - + c.NewBatch(4).SendCloseFromClient(); // now the first send should match up with the first recv - cqv.Expect(grpc_core::CqVerifier::tag(103), true); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); + Expect(103, true); + Expect(4, true); + Step(); // and the next recv should be ready immediately also (and empty) - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv2; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(104), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(104), true); - cqv.Verify(); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(4), nullptr); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), - grpc_core::CqVerifier::tag(105), nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - cqv.Expect(grpc_core::CqVerifier::tag(105), true); - cqv.Expect(grpc_core::CqVerifier::tag(4), true); - cqv.Verify(); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); - GPR_ASSERT(request_payload_recv2 == nullptr); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv1); + CoreEnd2endTest::IncomingMessage request_payload_recv2; + s.NewBatch(104).RecvMessage(request_payload_recv2); + Expect(104, true); + Step(); + + CoreEnd2endTest::IncomingStatusOnClient server_status; + c.NewBatch(4).RecvStatusOnClient(server_status); + CoreEnd2endTest::IncomingCloseOnServer client_close; + s.NewBatch(105) + .RecvCloseOnServer(client_close) + .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {}); + Expect(105, true); + Expect(4, true); + Step(); + + EXPECT_EQ(server_status.status(), GRPC_STATUS_OK); + EXPECT_EQ(server_status.message(), "xyz"); + EXPECT_EQ(s.method(), "/foo"); + EXPECT_FALSE(client_close.was_cancelled()); + EXPECT_EQ(request_payload_recv1.payload(), "hello world"); + EXPECT_TRUE(request_payload_recv2.is_end_of_stream()); } - -void write_buffering_at_end(const CoreTestConfiguration& config) { - test_invoke_request_with_payload(config); -} - -void write_buffering_at_end_pre_init(void) {} +} // namespace +} // namespace grpc_core diff --git a/test/core/iomgr/ios/CFStreamTests/Podfile b/test/core/iomgr/ios/CFStreamTests/Podfile index 0da1b2a9512..176226696a1 100644 --- a/test/core/iomgr/ios/CFStreamTests/Podfile +++ b/test/core/iomgr/ios/CFStreamTests/Podfile @@ -9,7 +9,6 @@ GRPC_LOCAL_SRC = '../../../../..' # Install the dependencies in the main target plus all test targets. target 'CFStreamTests' do pod 'gRPC-Core', :path => GRPC_LOCAL_SRC - pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true end diff --git a/test/cpp/cocoapods/Podfile b/test/cpp/cocoapods/Podfile index e3ab369b31a..26e68de0b17 100644 --- a/test/cpp/cocoapods/Podfile +++ b/test/cpp/cocoapods/Podfile @@ -12,7 +12,6 @@ GRPC_LOCAL_SRC = '../../..' ).each do |target_name| target target_name do pod 'gRPC-Core', :path => GRPC_LOCAL_SRC - pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC pod 'gRPC-C++', :path => GRPC_LOCAL_SRC pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true end diff --git a/tools/buildgen/extract_metadata_from_bazel_xml.py b/tools/buildgen/extract_metadata_from_bazel_xml.py index 84aafd88e3b..c8810193c09 100755 --- a/tools/buildgen/extract_metadata_from_bazel_xml.py +++ b/tools/buildgen/extract_metadata_from_bazel_xml.py @@ -993,13 +993,6 @@ _BUILD_EXTRA_METADATA = { '_RENAME': 'grpc++_test_util' }, - # end2end test support libraries - 'test/core/end2end:end2end_tests': { - 'language': 'c', - 'build': 'private', - '_RENAME': 'end2end_tests' - }, - # benchmark support libraries 'test/cpp/microbenchmarks:helpers': { 'language': 'c++', diff --git a/tools/buildgen/generate_build_additions.sh b/tools/buildgen/generate_build_additions.sh index 46ff7e9e51e..c890b5372fd 100755 --- a/tools/buildgen/generate_build_additions.sh +++ b/tools/buildgen/generate_build_additions.sh @@ -24,7 +24,6 @@ gen_build_yaml_dirs=" \ src/upb \ src/zlib \ src/c-ares \ - test/core/end2end \ test/cpp/naming" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index a7264007bda..a491456422e 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1,120 +1,6 @@ [ - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "bad_server_response_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "bad_ssl_alpn_test", - "platforms": [ - "linux", - "mac", - "posix" - ], - "uses_polling": true - }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "bad_ssl_cert_test", - "platforms": [ - "linux", - "mac", - "posix" - ], - "uses_polling": true - }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "connection_refused_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "dualstack_socket_test", - "platforms": [ - "linux", - "mac", - "posix" - ], - "uses_polling": true - }, { "args": [], "benchmark": false, @@ -137,54 +23,6 @@ ], "uses_polling": true }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "goaway_server_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "invalid_call_argument_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, { "args": [], "benchmark": false, @@ -209,30 +47,6 @@ ], "uses_polling": true }, - { - "args": [], - "benchmark": false, - "ci_platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "gtest": false, - "language": "c", - "name": "no_server_test", - "platforms": [ - "linux", - "mac", - "posix", - "windows" - ], - "uses_polling": true - }, { "args": [], "benchmark": false, @@ -1033,6 +847,74 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "bad_server_response_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "bad_ssl_alpn_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "bad_ssl_cert_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -2203,6 +2085,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "connection_refused_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -2323,6 +2229,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "core_end2end_tests", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -2537,6 +2467,28 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "dualstack_socket_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -3293,6 +3245,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "goaway_server_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -4243,6 +4219,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "invalid_call_argument_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, @@ -4973,6 +4973,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "no_server_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false,