[tests] Convert core e2e tests to gtest (#32603)

Notes:
- `+trace` fixtures haven't run since 2016, so they're disabled for now
(7ad2d0b463 (diff-780fce7267c34170c1d0ea15cc9f65a7f4b79fefe955d185c44e8b3251cf9e38R76))
- all current fixtures define `FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER`
and hence `authority_not_supported` has not been run in years - deleted
- bad_hostname similarly hasn't been triggered in a long while, so
deleted
- load_reporting_hook has never been enabled, so deleted
(f23fb4cf31/test/core/end2end/generate_tests.bzl (L145-L148))
- filter_latency & filter_status_code rely on global variables and so
don't convert particularly cleanly - and their value seems marginal, so
deleted

---------

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/32792/head
Craig Tiller 2 years ago committed by GitHub
parent d551a512c8
commit 724441d85b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitattributes
  2. 1174
      CMakeLists.txt
  3. 650
      build_autogenerated.yaml
  4. 153
      gRPC-Core.podspec
  5. 114
      grpc.gyp
  6. 2
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  7. 8
      src/core/ext/transport/chttp2/transport/frame_ping.cc
  8. 3
      src/core/ext/transport/chttp2/transport/frame_ping.h
  9. 1
      src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
  10. 2
      src/core/ext/transport/chttp2/transport/internal.h
  11. 23
      src/core/lib/debug/trace.cc
  12. 16
      src/core/lib/debug/trace.h
  13. 33
      src/core/lib/iomgr/timer_generic.cc
  14. 2
      src/core/lib/slice/slice.h
  15. 8
      src/objective-c/tests/BUILD
  16. 330
      src/objective-c/tests/CronetTests/CoreCronetEnd2EndTests.mm
  17. 1
      src/objective-c/tests/Podfile
  18. 22
      templates/gRPC-Core.podspec.template
  19. 72
      templates/test/core/end2end/end2end_defs.include
  20. 4
      templates/test/core/end2end/end2end_tests.cc.template
  21. 1
      test/core/bad_client/generate_tests.bzl
  22. 212
      test/core/end2end/BUILD
  23. 7
      test/core/end2end/README
  24. 73
      test/core/end2end/cq_verifier.cc
  25. 32
      test/core/end2end/cq_verifier.h
  26. 1070
      test/core/end2end/end2end_test_main.cc
  27. 49
      test/core/end2end/end2end_test_utils.cc
  28. 1006
      test/core/end2end/end2end_tests.cc
  29. 642
      test/core/end2end/end2end_tests.h
  30. 87
      test/core/end2end/fixtures/h2_census.cc
  31. 96
      test/core/end2end/fixtures/h2_compress.cc
  32. 89
      test/core/end2end/fixtures/h2_fakesec.cc
  33. 111
      test/core/end2end/fixtures/h2_fd.cc
  34. 72
      test/core/end2end/fixtures/h2_full+pipe.cc
  35. 95
      test/core/end2end/fixtures/h2_full+trace.cc
  36. 58
      test/core/end2end/fixtures/h2_full.cc
  37. 66
      test/core/end2end/fixtures/h2_full_no_retry.cc
  38. 119
      test/core/end2end/fixtures/h2_http_proxy.cc
  39. 84
      test/core/end2end/fixtures/h2_insecure.cc
  40. 65
      test/core/end2end/fixtures/h2_local_abstract_uds_percent_encoded.cc
  41. 59
      test/core/end2end/fixtures/h2_local_ipv4.cc
  42. 59
      test/core/end2end/fixtures/h2_local_ipv6.cc
  43. 69
      test/core/end2end/fixtures/h2_local_uds.cc
  44. 69
      test/core/end2end/fixtures/h2_local_uds_percent_encoded.cc
  45. 58
      test/core/end2end/fixtures/h2_oauth2_tls12.cc
  46. 59
      test/core/end2end/fixtures/h2_oauth2_tls13.cc
  47. 113
      test/core/end2end/fixtures/h2_proxy.cc
  48. 86
      test/core/end2end/fixtures/h2_sockpair+trace.cc
  49. 53
      test/core/end2end/fixtures/h2_sockpair.cc
  50. 59
      test/core/end2end/fixtures/h2_sockpair_1byte.cc
  51. 72
      test/core/end2end/fixtures/h2_sockpair_with_minstack.cc
  52. 68
      test/core/end2end/fixtures/h2_ssl_cred_reload_tls12.cc
  53. 68
      test/core/end2end/fixtures/h2_ssl_cred_reload_tls13.cc
  54. 188
      test/core/end2end/fixtures/h2_ssl_proxy.cc
  55. 65
      test/core/end2end/fixtures/h2_ssl_tls12.cc
  56. 65
      test/core/end2end/fixtures/h2_ssl_tls13.cc
  57. 58
      test/core/end2end/fixtures/h2_tls_certwatch_async_tls1_3.cc
  58. 58
      test/core/end2end/fixtures/h2_tls_certwatch_sync_tls1_2.cc
  59. 4
      test/core/end2end/fixtures/h2_tls_common.h
  60. 58
      test/core/end2end/fixtures/h2_tls_simple.cc
  61. 58
      test/core/end2end/fixtures/h2_tls_static_async_tls1_3.cc
  62. 69
      test/core/end2end/fixtures/h2_uds.cc
  63. 69
      test/core/end2end/fixtures/h2_uds_abstract.cc
  64. 55
      test/core/end2end/fixtures/inproc.cc
  65. 2
      test/core/end2end/fixtures/inproc_fixture.h
  66. 2
      test/core/end2end/fixtures/local_util.h
  67. 2
      test/core/end2end/fixtures/secure_fixture.h
  68. 58
      test/core/end2end/fixtures/sockpair_fixture.h
  69. 53
      test/core/end2end/gen_build_yaml.py
  70. 499
      test/core/end2end/generate_tests.bzl
  71. 9
      test/core/end2end/h2_ssl_cert_test.cc
  72. 17
      test/core/end2end/run.sh
  73. 142
      test/core/end2end/tests/authority_not_supported.cc
  74. 124
      test/core/end2end/tests/bad_hostname.cc
  75. 355
      test/core/end2end/tests/bad_ping.cc
  76. 340
      test/core/end2end/tests/binary_metadata.cc
  77. 668
      test/core/end2end/tests/call_creds.cc
  78. 192
      test/core/end2end/tests/call_host_override.cc
  79. 256
      test/core/end2end/tests/cancel_after_accept.cc
  80. 211
      test/core/end2end/tests/cancel_after_client_done.cc
  81. 241
      test/core/end2end/tests/cancel_after_invoke.cc
  82. 292
      test/core/end2end/tests/cancel_after_round_trip.cc
  83. 195
      test/core/end2end/tests/cancel_before_invoke.cc
  84. 54
      test/core/end2end/tests/cancel_in_a_vacuum.cc
  85. 36
      test/core/end2end/tests/cancel_test_helpers.h
  86. 167
      test/core/end2end/tests/cancel_with_status.cc
  87. 303
      test/core/end2end/tests/channelz.cc
  88. 234
      test/core/end2end/tests/client_streaming.cc
  89. 943
      test/core/end2end/tests/compressed_payload.cc
  90. 234
      test/core/end2end/tests/connectivity.cc
  91. 195
      test/core/end2end/tests/default_host.cc
  92. 182
      test/core/end2end/tests/disappearing_server.cc
  93. 59
      test/core/end2end/tests/empty_batch.cc
  94. 187
      test/core/end2end/tests/filter_causes_close.cc
  95. 238
      test/core/end2end/tests/filter_context.cc
  96. 592
      test/core/end2end/tests/filter_init_fails.cc
  97. 289
      test/core/end2end/tests/filter_latency.cc
  98. 353
      test/core/end2end/tests/filter_status_code.cc
  99. 211
      test/core/end2end/tests/filtered_metadata.cc
  100. 173
      test/core/end2end/tests/graceful_server_shutdown.cc
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitattributes vendored

@ -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

1174
CMakeLists.txt generated

File diff suppressed because it is too large Load Diff

@ -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

153
gRPC-Core.podspec generated

@ -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

114
grpc.gyp generated

@ -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',

@ -369,6 +369,8 @@ static void read_channel_args(grpc_chttp2_transport* t,
.GetObjectRef<grpc_core::channelz::SocketNode::Security>());
}
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) {

@ -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;
}

@ -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

@ -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<Memento> entries;
entries.reserve(num_entries_);
for (size_t i = 0; i < num_entries_; i++) {

@ -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<grpc_event_engine::experimental::EventEngine::TaskHandle>
next_bdp_ping_timer_handle;

@ -24,6 +24,7 @@
#include <string>
#include <type_traits>
#include <utility>
#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<std::string, bool>& 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<TraceFlag>::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());
}

@ -22,10 +22,8 @@
#include <grpc/support/port_platform.h>
#include <atomic>
// 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 <map>
#include <string>
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<std::string, bool>& values);
private:
static void LogAllTracers();
@ -101,6 +100,15 @@ class DebugOnlyTraceFlag {
};
#endif
class SavedTraceFlags {
public:
SavedTraceFlags();
void Restore();
private:
std::map<std::string, bool> values_;
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_DEBUG_TRACE_H

@ -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<int>(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<int>(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<int>(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<int>(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<int>(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;
}

@ -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

@ -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",
],
)

@ -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 <XCTest/XCTest.h>
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#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 <Cronet/Cronet.h>
#include <grpc/grpc_cronet.h>
#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<CronetFixture>();
}},
};
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

@ -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

@ -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

@ -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 <stdbool.h>
#include <string.h>
#include "absl/strings/str_format.h"
#include <grpc/support/log.h>
#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]));
}
}</%def>

@ -1,4 +0,0 @@
%YAML 1.2
--- |
<%namespace file="end2end_defs.include" import="*"/>\
${end2end_selector(core_end2end_tests.keys())}

@ -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",

@ -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",
],
)

@ -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

@ -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 <grpc/byte_buffer.h>
#include <grpc/compression.h>
@ -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<void(Failure)> 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<std::string> CqVerifier::ToStrings() const {
std::vector<std::string> 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<Maybe>(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<Maybe>(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

@ -21,9 +21,11 @@
#include <stdint.h>
#include <functional>
#include <string>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/types/variant.h"
#include <grpc/grpc.h>
@ -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<void(bool success)> action;
};
// MaybePerformAction - run a function if a tag is seen
struct MaybePerformAction {
std::function<void(bool success)> action;
};
using ExpectedResult =
absl::variant<bool, Maybe, AnyStatus, PerformAction, MaybePerformAction>;
struct Failure {
SourceLocation location;
std::string message;
std::vector<std::string> expected;
};
using ExpectedResult = absl::variant<bool, Maybe, AnyStatus>;
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<void(Failure)> fail = FailUsingGprCrash);
~CqVerifier();
CqVerifier(const CqVerifier&) = delete;
@ -74,6 +100,7 @@ class CqVerifier {
SourceLocation location = SourceLocation());
std::string ToString() const;
std::vector<std::string> ToStrings() const;
static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
@ -93,6 +120,7 @@ class CqVerifier {
grpc_completion_queue* const cq_;
std::vector<Expectation> expectations_;
mutable absl::AnyInvocable<void(Failure)> fail_;
};
} // namespace grpc_core

File diff suppressed because it is too large Load Diff

@ -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 <grpc/slice.h>
#include <grpc/support/log.h>
#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));
}
}

File diff suppressed because it is too large Load Diff

@ -19,20 +19,46 @@
#ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H
#define GRPC_TEST_CORE_END2END_END2END_TESTS_H
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#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 <grpc/byte_buffer.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include <grpc/grpc_security.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<grpc_byte_buffer, void (*)(grpc_byte_buffer*)>;
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<std::unique_ptr<CoreTestFixture>(
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<const CoreTestConfiguration*> {
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<UnregisteredCall>(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<std::string> host;
};
absl::variant<void*, UnregisteredCall> 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<std::string> 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<grpc_metadata_array> metadata_ =
std::make_unique<grpc_metadata_array>(
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<char*>(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<std::string> 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> data_ = std::make_unique<Data>();
};
// 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<std::pair<absl::string_view, absl::string_view>>
md,
uint32_t flags = 0,
absl::optional<grpc_compression_level> 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<std::pair<absl::string_view, absl::string_view>>
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 <typename T>
class SpecificThing final : public Thing {
public:
template <typename... Args>
explicit SpecificThing(Args&&... args)
: t_(std::forward<Args>(args)...) {}
SpecificThing() = default;
T& get() { return t_; }
private:
T t_;
};
// Make a thing of type T, and return a reference to it.
template <typename T, typename... Args>
T& Make(Args&&... args) {
things_.emplace_back(new SpecificThing<T>(std::forward<Args>(args)...));
return static_cast<SpecificThing<T>*>(things_.back().get())->get();
}
grpc_call* call_;
const int tag_;
std::vector<grpc_op> ops_;
std::vector<std::unique_ptr<Thing>> 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<std::string> 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<grpc_auth_context, void (*)(grpc_auth_context*)>
GetAuthContext() {
return std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>(
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<std::string> GetInitialMetadata(absl::string_view key) const;
// Return the peer address.
absl::optional<std::string> GetPeer() { return impl_->call.GetPeer(); }
// Return the auth context.
std::unique_ptr<grpc_auth_context, void (*)(grpc_auth_context*)>
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<GRPC_COMPRESS_ALGORITHMS_COUNT> GetEncodingsAcceptedByPeer() {
return BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT>::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> 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<Duration> 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<CqVerifier>(
fixture().cq(), CqVerifier::FailUsingGtestFail);
}
return *cq_verifier_;
}
std::unique_ptr<CoreTestFixture> fixture_;
std::unique_ptr<CqVerifier> 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

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#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<CensusFixture>();
}},
};
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#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<CompressionFixture>();
}},
};
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#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<FakesecFixture>();
}}};
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;
}

@ -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 <functional>
#include <memory>
#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 <fcntl.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/grpc_posix.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#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<FdFixture>();
}},
};
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

@ -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 <functional>
#include <memory>
#include <grpc/grpc.h>
#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 <string.h>
#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<InsecureFixture>();
}},
};
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

@ -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 <grpc/support/port_platform.h>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/port.h" // IWYU pragma: keep
#ifdef GRPC_POSIX_SOCKET
#include <unistd.h>
#endif
#include <functional>
#include <memory>
#include <string>
#include <grpc/support/log.h>
#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<InsecureFixture>();
}},
};
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<InsecureFixture>();
}},
};
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<NoRetryFixture>();
}},
};
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;
}

@ -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 <string.h>
#include <functional>
#include <initializer_list>
#include <memory>
#include <string>
#include "absl/strings/str_format.h"
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#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<std::string> 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<HttpProxyFilter>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#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<InsecureCredsFixture>();
}},
};
} // 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;
}

@ -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 <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <initializer_list>
#include <memory>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#include <grpc/support/time.h>
#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<int> 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<LocalTestFixture>(
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;
}

@ -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 <unistd.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<LocalTestFixture>(
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;
}

@ -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 <unistd.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<LocalTestFixture>(
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;
}

@ -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 <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <initializer_list>
#include <memory>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#include <grpc/support/time.h>
#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<int> 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<LocalTestFixture>(
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;
}

@ -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 <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <initializer_list>
#include <memory>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#include <grpc/support/time.h>
#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<int> 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<LocalTestFixture>(
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;
}

@ -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 <stdio.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<Oauth2Fixture>(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;
}

@ -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 <stdio.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<Oauth2Fixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#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<ProxyFixture>(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;
}

@ -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 <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#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 <unistd.h>
#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<SockpairFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<SockpairFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<SockpairFixture>(
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<SockpairWithMinstackFixture>(
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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<SslCredReloadFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<SslCredReloadFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#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<const char*> GRPC_SLICE_START_PTR(cert_slice);
const char* server_key =
reinterpret_cast<const char*> 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<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
{const_cast<char*>("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<const char*> GRPC_SLICE_START_PTR(cert_slice);
const char* server_key =
reinterpret_cast<const char*> 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<SslProxyFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<SslTlsFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security_constants.h>
#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<SslTlsFixture>(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;
}

@ -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 <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#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<TlsFixture>(
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;
}

@ -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 <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#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<TlsFixture>(
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;
}

@ -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

@ -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 <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#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<TlsFixture>(
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;
}

@ -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 <functional>
#include <memory>
#include <string>
#include "absl/types/optional.h"
#include <grpc/grpc.h>
#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<TlsFixture>(
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;
}

@ -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 <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <initializer_list>
#include <memory>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpc/support/time.h>
#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<int> 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<InsecureFixture>(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;
}

@ -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 <inttypes.h>
#include <unistd.h>
#include <atomic>
#include <functional>
#include <initializer_list>
#include <memory>
#include "absl/strings/str_format.h"
#include <grpc/grpc.h>
#include <grpc/support/time.h>
#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<int> 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<InsecureFixture>(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;
}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#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<InprocFixture>();
},
}};
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;
}

@ -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);

@ -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);

@ -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()))

@ -15,8 +15,11 @@
#ifndef GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H
#define GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H
#include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/status.h>
@ -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

@ -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()

@ -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,
)

@ -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<CoreTestConfigWrapper> {
}
void TearDown() override { fixture_.reset(); }
std::unique_ptr<CoreTestFixture> fixture_;
std::unique_ptr<grpc_core::CoreTestFixture> fixture_;
};
TEST_P(H2SslCertTest, SimpleRequestBody) {

@ -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
"$@"

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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) {}

@ -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 <string.h>
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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) {}

@ -16,104 +16,41 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<size_t>(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<size_t>(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<size_t>(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<size_t>(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

@ -16,272 +16,104 @@
//
//
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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_channel_args*>(grpc_core::CoreConfiguration::Get()
.channel_args_preconditioning()
.PreconditionChannelArgs(client_args)
.ToC()
.release());
server_args =
const_cast<grpc_channel_args*>(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<size_t>(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<size_t>(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<size_t>(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

@ -16,56 +16,34 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include "absl/types/optional.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<size_t>(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<size_t>(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

@ -16,162 +16,54 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include "absl/types/optional.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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

@ -16,216 +16,80 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include <string>
#include <grpc/byte_buffer.h>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<char*>(GRPC_ARG_SERVICE_CONFIG);
arg.value.string = const_cast<char*>(
"{\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<size_t>(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<size_t>(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<CancellationMode> 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<CancelCancellationMode>(),
Duration::Seconds(5));
}
void cancel_after_accept(const CoreTestConfiguration& config) {
unsigned i;
TEST_P(CoreDeadlineTest, DeadlineAfterAccept) {
CancelAfterAccept(*this, std::make_unique<DeadlineCancellationMode>(),
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<DeadlineCancellationMode>(),
Duration::Infinity());
}
void cancel_after_accept_pre_init(void) {}
} // namespace grpc_core

@ -16,183 +16,62 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<CancellationMode> 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<CancelCancellationMode>());
}
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<DeadlineCancellationMode>());
}
void cancel_after_client_done_pre_init(void) {}
} // namespace grpc_core

@ -16,143 +16,128 @@
//
//
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<CancellationMode> 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<CancellationMode> 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<CancellationMode> 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<CancellationMode> 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<CancelCancellationMode>());
}
TEST_P(CoreEnd2endTest, CancelAfterInvoke5) {
CancelAfterInvoke5(*this, std::make_unique<CancelCancellationMode>());
}
TEST_P(CoreEnd2endTest, CancelAfterInvoke4) {
CancelAfterInvoke4(*this, std::make_unique<CancelCancellationMode>());
}
TEST_P(CoreEnd2endTest, CancelAfterInvoke3) {
CancelAfterInvoke3(*this, std::make_unique<CancelCancellationMode>());
}
TEST_P(CoreDeadlineTest, DeadlineAfterInvoke6) {
CancelAfterInvoke6(*this, std::make_unique<DeadlineCancellationMode>());
}
TEST_P(CoreDeadlineTest, DeadlineAfterInvoke5) {
CancelAfterInvoke5(*this, std::make_unique<DeadlineCancellationMode>());
}
// 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<DeadlineCancellationMode>());
}
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<DeadlineCancellationMode>());
}
void cancel_after_invoke_pre_init(void) {}
} // namespace grpc_core

@ -16,247 +16,83 @@
//
//
#include <string.h>
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<CancellationMode> 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<char*>(GRPC_ARG_SERVICE_CONFIG);
arg.value.string = const_cast<char*>(
"{\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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<CancelCancellationMode>(),
Duration::Seconds(5));
}
void cancel_after_round_trip(const CoreTestConfiguration& config) {
unsigned i;
TEST_P(CoreDeadlineTest, DeadlineAfterRoundTrip) {
CancelAfterRoundTrip(*this, std::make_unique<DeadlineCancellationMode>(),
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<DeadlineCancellationMode>(),
Duration::Infinity());
}
void cancel_after_round_trip_pre_init(void) {}
} // namespace
} // namespace grpc_core

@ -16,136 +16,93 @@
//
//
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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

@ -16,58 +16,18 @@
//
//
#include <functional>
#include <memory>
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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

@ -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 <grpc/grpc.h>
#include <grpc/status.h>
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

@ -16,122 +16,89 @@
//
//
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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

@ -18,252 +18,145 @@
#include "src/core/lib/channel/channelz.h"
#include <string.h>
#include <functional>
#include <memory>
#include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(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<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
1024 * 1024),
grpc_channel_arg_integer_create(
const_cast<char*>(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<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(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

@ -16,214 +16,70 @@
//
//
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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

@ -17,627 +17,414 @@
//
#include <stdint.h>
#include <string.h>
#include <functional>
#include <initializer_list>
#include <memory>
#include <string>
#include <utility>
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "gtest/gtest.h"
#include <grpc/byte_buffer.h>
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<GRPC_COMPRESS_ALGORITHMS_COUNT>()
.SetAll(true)
.Set(algorithm_to_disable, false)
.ToInt<uint32_t>());
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<GRPC_COMPRESS_ALGORITHMS_COUNT>()
.SetAll(true)
.Set(algorithm, false)
.ToInt<uint32_t>());
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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<std::pair<absl::string_view, absl::string_view>>
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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<size_t>(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

@ -16,213 +16,73 @@
//
//
#include <functional>
#include <memory>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#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<child_events*>(arg);
grpc_event ev;
gpr_event_set(&ce->started, reinterpret_cast<void*>(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<CallbackContext*>(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<void*>(1));
}
static void cb_shutdown(grpc_completion_queue_functor* functor,
int /*success*/) {
CallbackContext* cb_ctx = reinterpret_cast<CallbackContext*>(functor);
gpr_log(GPR_DEBUG, "cb_shutdown called, nothing to do");
gpr_event_set(&cb_ctx->finished, reinterpret_cast<void*>(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

@ -16,164 +16,55 @@
//
//
#include <string.h>
#include "absl/types/optional.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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

@ -16,117 +16,41 @@
//
//
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<size_t>(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<size_t>(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) {}

@ -16,60 +16,17 @@
//
//
#include <functional>
#include <memory>
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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

@ -17,137 +17,27 @@
//
#include <stdint.h>
#include <string.h>
#include <functional>
#include <memory>
#include "absl/status/status.h"
#include "gtest/gtest.h"
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<grpc_call_element*>(arg);
call_data* calld = static_cast<call_data*>(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<call_data*>(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

@ -17,169 +17,31 @@
//
#include <limits.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <memory>
#include <vector>
#include "absl/status/status.h"
#include "gtest/gtest.h"
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<call_data*>(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<call_data*>(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

@ -17,22 +17,17 @@
//
#include <limits.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <vector>
#include "absl/status/status.h"
#include "absl/types/optional.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<grpc_core::ServerMetadataHandle> {
return grpc_core::Immediate(grpc_core::ServerMetadataFromStatus(
[](grpc_channel_element*, CallArgs,
NextPromiseFactory) -> ArenaPromise<ServerMetadataHandle> {
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

@ -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 <limits.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <vector>
#include "absl/status/status.h"
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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); }

@ -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 <limits.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <memory>
#include <vector>
#include "absl/status/status.h"
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<final_status_data*>(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<final_status_data*>(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<final_status_data*>(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<final_status_data*>(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);
}

@ -16,175 +16,64 @@
//
//
#include <string.h>
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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<size_t>(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

@ -16,150 +16,45 @@
//
//
#include <string.h>
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#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<CoreTestFixture> 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<size_t>(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<size_t>(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

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save