[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/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.h linguist-generated=true
src/ruby/ext/grpc/rb_grpc_imports.generated.c 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/security/grpc_tls_credentials_options_comparator_test.cc linguist-generated=true
test/core/surface/public_headers_must_be_c89.c linguist-generated=true test/core/surface/public_headers_must_be_c89.c linguist-generated=true
tools/doxygen/Doxyfile.c++.internal 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_posix.c
- third_party/address_sorting/address_sorting_windows.c - third_party/address_sorting/address_sorting_windows.c
deps: [] 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 - name: gpr
build: all build: all
language: c language: c
@ -4185,118 +4057,6 @@ libs:
deps: deps:
- grpc++ - grpc++
targets: 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 - name: fd_conservation_posix_test
build: test build: test
language: c language: c
@ -4334,26 +4094,6 @@ targets:
- linux - linux
- posix - posix
- mac - 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 - name: multiple_server_queues_test
build: test build: test
language: c language: c
@ -4362,16 +4102,6 @@ targets:
- test/core/end2end/multiple_server_queues_test.cc - test/core/end2end/multiple_server_queues_test.cc
deps: deps:
- grpc_test_util - 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 - name: pollset_windows_starvation_test
build: test build: test
language: c language: c
@ -4905,21 +4635,146 @@ targets:
deps: deps:
- grpc_test_util - grpc_test_util
uses_polling: false 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 gtest: true
build: test build: test
language: c++ language: c++
headers: [] headers:
- test/core/end2end/cq_verifier.h
src: src:
- test/cpp/common/auth_property_iterator_test.cc - test/core/end2end/bad_server_response_test.cc
- test/core/end2end/cq_verifier.cc
deps: deps:
- grpc++_test_util - grpc_test_util
uses_polling: false - name: bad_ssl_alpn_test
- name: authorization_matchers_test
gtest: true gtest: true
build: test build: test
language: c++ language: c++
headers: headers:
- test/core/end2end/cq_verifier.h
- test/core/util/cmdline.h - test/core/util/cmdline.h
- test/core/util/evaluate_args_test_util.h - test/core/util/evaluate_args_test_util.h
- test/core/util/fuzzer_util.h - test/core/util/fuzzer_util.h
@ -4934,7 +4789,8 @@ targets:
- test/core/util/subprocess.h - test/core/util/subprocess.h
- test/core/util/tracer_util.h - test/core/util/tracer_util.h
src: 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/cmdline.cc
- test/core/util/fuzzer_util.cc - test/core/util/fuzzer_util.cc
- test/core/util/grpc_profiler.cc - test/core/util/grpc_profiler.cc
@ -4949,36 +4805,16 @@ targets:
- test/core/util/tracer_util.cc - test/core/util/tracer_util.cc
deps: deps:
- grpc_test_util - grpc_test_util
- name: authorization_policy_provider_test platforms:
gtest: true - linux
build: test - posix
language: c++ - mac
headers: [] - name: bad_ssl_cert_test
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 gtest: true
build: test build: test
language: c++ language: c++
headers: headers:
- test/core/end2end/cq_verifier.h
- test/core/util/cmdline.h - test/core/util/cmdline.h
- test/core/util/evaluate_args_test_util.h - test/core/util/evaluate_args_test_util.h
- test/core/util/fuzzer_util.h - test/core/util/fuzzer_util.h
@ -4993,7 +4829,8 @@ targets:
- test/core/util/subprocess.h - test/core/util/subprocess.h
- test/core/util/tracer_util.h - test/core/util/tracer_util.h
src: 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/cmdline.cc
- test/core/util/fuzzer_util.cc - test/core/util/fuzzer_util.cc
- test/core/util/grpc_profiler.cc - test/core/util/grpc_profiler.cc
@ -5008,26 +4845,10 @@ targets:
- test/core/util/tracer_util.cc - test/core/util/tracer_util.cc
deps: deps:
- grpc_test_util - grpc_test_util
- name: b64_test platforms:
gtest: true - linux
build: test - posix
language: c++ - mac
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_streaming_id_bad_client_test - name: bad_streaming_id_bad_client_test
gtest: true gtest: true
build: test build: test
@ -6225,6 +6046,17 @@ targets:
- test/core/end2end/cq_verifier.cc - test/core/end2end/cq_verifier.cc
deps: deps:
- grpc_test_util - 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 - name: connectivity_state_test
gtest: true gtest: true
build: test build: test
@ -6330,6 +6162,126 @@ targets:
deps: deps:
- grpc - grpc
uses_polling: false 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 - name: cpp_impl_of_test
gtest: true gtest: true
build: test build: test
@ -6425,6 +6377,21 @@ targets:
- test/core/gprpp/dual_ref_counted_test.cc - test/core/gprpp/dual_ref_counted_test.cc
deps: deps:
- grpc_test_util - 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 - name: duplicate_header_bad_client_test
gtest: true gtest: true
build: test build: test
@ -7968,6 +7935,17 @@ targets:
- test/cpp/end2end/generic_end2end_test.cc - test/cpp/end2end/generic_end2end_test.cc
deps: deps:
- grpc++_test_util - 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 - name: google_c2p_resolver_test
gtest: true gtest: true
build: test build: test
@ -8505,12 +8483,14 @@ targets:
- test/core/end2end/fixtures/local_util.h - test/core/end2end/fixtures/local_util.h
- test/core/end2end/fixtures/secure_fixture.h - test/core/end2end/fixtures/secure_fixture.h
- test/core/end2end/fixtures/sockpair_fixture.h - test/core/end2end/fixtures/sockpair_fixture.h
- test/core/end2end/tests/cancel_test_helpers.h
src: src:
- test/core/end2end/cq_verifier.cc - test/core/end2end/cq_verifier.cc
- test/core/end2end/data/client_certs.cc - test/core/end2end/data/client_certs.cc
- test/core/end2end/data/server1_cert.cc - test/core/end2end/data/server1_cert.cc
- test/core/end2end/data/server1_key.cc - test/core/end2end/data/server1_key.cc
- test/core/end2end/data/test_root_cert.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/fixtures/local_util.cc
- test/core/end2end/h2_ssl_cert_test.cc - test/core/end2end/h2_ssl_cert_test.cc
deps: deps:
@ -9043,6 +9023,17 @@ targets:
deps: deps:
- grpc++_test_config - grpc++_test_config
- grpc++_test_util - 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 - name: iocp_test
gtest: true gtest: true
build: test build: test
@ -9676,6 +9667,17 @@ targets:
- test/core/gprpp/no_destruct_test.cc - test/core/gprpp/no_destruct_test.cc
deps: [] deps: []
uses_polling: false 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 - name: nonblocking_test
gtest: true gtest: true
build: test 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' 'third_party/objective_c/Cronet/bidirectional_stream_c.h'
end 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 # patch include of openssl to openssl_grpc
s.prepare_command = <<-END_OF_COMMAND s.prepare_command = <<-END_OF_COMMAND
set -e set -e

114
grpc.gyp generated

@ -173,120 +173,6 @@
'third_party/address_sorting/address_sorting_windows.c', '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', 'target_name': 'gpr',
'type': 'static_library', 'type': 'static_library',

@ -369,6 +369,8 @@ static void read_channel_args(grpc_chttp2_transport* t,
.GetObjectRef<grpc_core::channelz::SocketNode::Security>()); .GetObjectRef<grpc_core::channelz::SocketNode::Security>());
} }
t->ack_pings = channel_args.GetBool("grpc.http2.ack_pings").value_or(true);
const int soft_limit = const int soft_limit =
channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1); channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1);
if (soft_limit < 0) { if (soft_limit < 0) {

@ -35,8 +35,6 @@
#include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/lib/gprpp/time.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 grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) {
grpc_slice slice = GRPC_SLICE_MALLOC(9 + 8); grpc_slice slice = GRPC_SLICE_MALLOC(9 + 8);
uint8_t* p = GRPC_SLICE_START_PTR(slice); 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; 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) { if (t->ping_ack_count == t->ping_ack_capacity) {
t->ping_ack_capacity = t->ping_ack_capacity =
std::max(t->ping_ack_capacity * 3 / 2, size_t{3}); 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(); 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, const grpc_slice& slice,
int is_last); 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 #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) { void HPackTable::MementoRingBuffer::Rebuild(uint32_t max_entries) {
if (max_entries == max_entries_) return; if (max_entries == max_entries_) return;
max_entries_ = max_entries;
std::vector<Memento> entries; std::vector<Memento> entries;
entries.reserve(num_entries_); entries.reserve(num_entries_);
for (size_t i = 0; i < num_entries_; i++) { 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 /// If start_bdp_ping_locked has been called
bool bdp_ping_started = false; bool bdp_ping_started = false;
// True if pings should be acked
bool ack_pings = true;
// next bdp ping timer handle // next bdp ping timer handle
absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle> absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
next_bdp_ping_timer_handle; next_bdp_ping_timer_handle;

@ -24,6 +24,7 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <utility>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
@ -77,12 +78,17 @@ void TraceFlagList::Add(TraceFlag* flag) {
void TraceFlagList::LogAllTracers() { void TraceFlagList::LogAllTracers() {
gpr_log(GPR_DEBUG, "available tracers:"); gpr_log(GPR_DEBUG, "available tracers:");
TraceFlag* t; for (TraceFlag* t = root_tracer_; t != nullptr; t = t->next_tracer_) {
for (t = root_tracer_; t != nullptr; t = t->next_tracer_) {
gpr_log(GPR_DEBUG, "\t%s", t->name_); 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 // Flags register themselves on the list during construction
TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) { TraceFlag::TraceFlag(bool default_enabled, const char* name) : name_(name) {
static_assert(std::is_trivially_destructible<TraceFlag>::value, 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); 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 } // namespace grpc_core
static void add(const char* beg, const char* end, char*** ss, size_t* ns) { 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); 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() { void grpc_tracer_init() {
parse(std::string(grpc_core::ConfigVars::Get().Trace()).c_str()); parse(std::string(grpc_core::ConfigVars::Get().Trace()).c_str());
} }

@ -22,10 +22,8 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <atomic> #include <atomic>
#include <map>
// TODO(veblush): Remove this deprecated function once codes depending on this #include <string>
// function are updated in the internal repo.
void grpc_tracer_init(const char* env_var_name);
void grpc_tracer_init(); void grpc_tracer_init();
void grpc_tracer_shutdown(void); void grpc_tracer_shutdown(void);
@ -37,6 +35,7 @@ class TraceFlagList {
public: public:
static bool Set(const char* name, bool enabled); static bool Set(const char* name, bool enabled);
static void Add(TraceFlag* flag); static void Add(TraceFlag* flag);
static void SaveTo(std::map<std::string, bool>& values);
private: private:
static void LogAllTracers(); static void LogAllTracers();
@ -101,6 +100,15 @@ class DebugOnlyTraceFlag {
}; };
#endif #endif
class SavedTraceFlags {
public:
SavedTraceFlags();
void Restore();
private:
std::map<std::string, bool> values_;
};
} // namespace grpc_core } // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_DEBUG_TRACE_H #endif // GRPC_SRC_CORE_LIB_DEBUG_TRACE_H

@ -338,7 +338,7 @@ static void timer_init(grpc_timer* timer, grpc_core::Timestamp deadline,
#endif #endif
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { 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(), timer, deadline.milliseconds_after_process_epoch(),
grpc_core::Timestamp::Now().milliseconds_after_process_epoch(), grpc_core::Timestamp::Now().milliseconds_after_process_epoch(),
closure, closure->cb); closure, closure->cb);
@ -374,7 +374,7 @@ static void timer_init(grpc_timer* timer, grpc_core::Timestamp deadline,
list_join(&shard->list, timer); list_join(&shard->list, timer);
} }
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { 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 " .. add to shard %d with queue_deadline_cap=%" PRId64
" => is_first_timer=%s", " => is_first_timer=%s",
static_cast<int>(shard - g_shards), 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) { if (is_first_timer) {
gpr_mu_lock(&g_shared_mutables.mu); gpr_mu_lock(&g_shared_mutables.mu);
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { 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()); shard->min_deadline.milliseconds_after_process_epoch());
} }
if (deadline < shard->min_deadline) { 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)]; timer_shard* shard = &g_shards[grpc_core::HashPointer(timer, g_num_shards)];
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { 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"); 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); grpc_core::Duration::FromSecondsAsDouble(deadline_delta);
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { 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), static_cast<int>(shard - g_shards),
shard->queue_deadline_cap.milliseconds_after_process_epoch()); 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 (timer_deadline < shard->queue_deadline_cap) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { 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()); timer_deadline.milliseconds_after_process_epoch());
} }
list_remove(timer); list_remove(timer);
@ -509,7 +509,7 @@ static grpc_timer* pop_one(timer_shard* shard, grpc_core::Timestamp now) {
grpc_timer* timer; grpc_timer* timer;
for (;;) { for (;;) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { 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), static_cast<int>(shard - g_shards),
grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false"); 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( grpc_core::Timestamp::FromMillisecondsAfterProcessEpoch(
timer->deadline); timer->deadline);
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) {
gpr_log(GPR_INFO, gpr_log(GPR_DEBUG,
" .. check top timer deadline=%" PRId64 " now=%" PRId64, " .. check top timer deadline=%" PRId64 " now=%" PRId64,
timer_deadline.milliseconds_after_process_epoch(), timer_deadline.milliseconds_after_process_epoch(),
now.milliseconds_after_process_epoch()); now.milliseconds_after_process_epoch());
} }
if (timer_deadline > now) return nullptr; if (timer_deadline > now) return nullptr;
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_trace)) { 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()); (now - timer_deadline).millis());
} }
timer->pending = false; 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); *new_min_deadline = compute_min_deadline(shard);
gpr_mu_unlock(&shard->mu); gpr_mu_unlock(&shard->mu);
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { 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); static_cast<int>(shard - g_shards), n);
} }
return 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)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) {
gpr_log( 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), static_cast<int>(g_shard_queue[0] - g_shards),
g_shard_queue[0]->min_deadline.milliseconds_after_process_epoch()); 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)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) {
gpr_log( gpr_log(
GPR_INFO, GPR_DEBUG,
" .. result --> %d" " .. result --> %d"
", shard[%d]->min_deadline %" PRId64 " --> %" PRId64 ", shard[%d]->min_deadline %" PRId64 " --> %" PRId64
", now=%" PRId64, ", now=%" PRId64,
@ -671,7 +671,7 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) {
*next = std::min(*next, min_timer); *next = std::min(*next, min_timer);
} }
if (GRPC_TRACE_FLAG_ENABLED(grpc_timer_check_trace)) { 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(), now.milliseconds_after_process_epoch(),
min_timer.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 #if GPR_ARCH_64
gpr_log( gpr_log(
GPR_INFO, GPR_DEBUG,
"TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64 "TIMER CHECK BEGIN: now=%" PRId64 " next=%s tls_min=%" PRId64
" glob_min=%" PRId64, " glob_min=%" PRId64,
now.milliseconds_after_process_epoch(), next_str.c_str(), 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))) gpr_atm_no_barrier_load((gpr_atm*)(&g_shared_mutables.min_timer)))
.milliseconds_after_process_epoch()); .milliseconds_after_process_epoch());
#else #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(), now.milliseconds_after_process_epoch(), next_str.c_str(),
min_timer.milliseconds_after_process_epoch()); min_timer.milliseconds_after_process_epoch());
#endif #endif
@ -718,7 +719,7 @@ static grpc_timer_check_result timer_check(grpc_core::Timestamp* next) {
} else { } else {
next_str = absl::StrCat(next->milliseconds_after_process_epoch()); 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; return r;
} }

@ -298,6 +298,8 @@ class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND MutableSlice
// Array access // Array access
uint8_t& operator[](size_t i) { return mutable_data()[i]; } 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 class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND Slice

@ -22,7 +22,6 @@ load(
"local_objc_grpc_library", "local_objc_grpc_library",
"proto_library_objc_wrapper", "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:resources.bzl", "apple_resource_bundle")
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test") load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test")
load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application", "tvos_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"]) exports_files(["LICENSE"])
grpc_end2end_tests()
proto_library_objc_wrapper( proto_library_objc_wrapper(
name = "messages_proto", name = "messages_proto",
srcs = ["RemoteTestClient/messages.proto"], srcs = ["RemoteTestClient/messages.proto"],
@ -188,7 +185,8 @@ grpc_objc_testing_library(
deps = [ deps = [
"InteropTests-lib", "InteropTests-lib",
"//src/objective-c:grpc_objc_client_core_cronet_testing", "//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", "//third_party/objective_c/Cronet:cronet_c_for_grpc",
], ],
) )
@ -206,7 +204,7 @@ grpc_objc_testing_library(
"//:grpc++_cronet_credentials", "//:grpc++_cronet_credentials",
"//src/objective-c:grpc_objc_client_core_cronet_testing", "//src/objective-c:grpc_objc_client_core_cronet_testing",
"//src/proto/grpc/testing:echo_proto", "//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 'gRPC/GRPCCoreCronet', :path => GRPC_LOCAL_SRC
pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
end end
target 'PerfTests' do target 'PerfTests' do

@ -76,7 +76,6 @@
set(address_sorting_unwanted_files)) set(address_sorting_unwanted_files))
| set(list_lib_files("re2", ("headers", ))))) | set(list_lib_files("re2", ("headers", )))))
grpc_abseil_specs = list_abseil_specs("grpc") 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 # TODO(jtattermusch): build.yaml is now generated from bazel build
# which doesn't have an explicit "grpc_cronet" target. Until it exists # 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_files = list(sorted(grpc_cronet_extra_impl_files))
grpc_cronet_public_headers = list(sorted(grpc_cronet_extra_public_headers)) 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| Pod::Spec.new do |s|
s.name = 'gRPC-Core' s.name = 'gRPC-Core'
@ -228,18 +218,6 @@
ss.source_files = ${ruby_multiline_list(grpc_cronet_files, 22)} ss.source_files = ${ruby_multiline_list(grpc_cronet_files, 22)}
end 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 # patch include of openssl to openssl_grpc
s.prepare_command = <<-END_OF_COMMAND s.prepare_command = <<-END_OF_COMMAND
set -e 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"], srcs = ["bad_client.cc"],
hdrs = ["bad_client.h"], hdrs = ["bad_client.h"],
language = "C++", language = "C++",
testonly = 1,
deps = [ deps = [
"//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util",
"//:grpc", "//:grpc",

@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
load(":generate_tests.bzl", "grpc_end2end_tests")
licenses(["notice"]) licenses(["notice"])
@ -21,15 +20,18 @@ grpc_package(name = "test/core/end2end")
grpc_cc_library( grpc_cc_library(
name = "cq_verifier", name = "cq_verifier",
testonly = 1,
srcs = ["cq_verifier.cc"], srcs = ["cq_verifier.cc"],
hdrs = ["cq_verifier.h"], hdrs = ["cq_verifier.h"],
external_deps = [ external_deps = [
"absl/functional:any_invocable",
"absl/strings", "absl/strings",
"absl/strings:str_format", "absl/strings:str_format",
"absl/types:variant", "absl/types:variant",
"gtest",
], ],
language = "C++", language = "C++",
visibility = ["//test:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//:debug_location", "//:debug_location",
"//:gpr", "//:gpr",
@ -50,7 +52,7 @@ grpc_cc_library(
], ],
hdrs = ["data/ssl_test_data.h"], hdrs = ["data/ssl_test_data.h"],
language = "C++", language = "C++",
visibility = ["//test:__subpackages__"], visibility = ["//:__subpackages__"],
) )
grpc_cc_library( 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( grpc_cc_library(
name = "fixture_support", name = "fixture_support",
testonly = 1,
srcs = ["fixtures/local_util.cc"], srcs = ["fixtures/local_util.cc"],
hdrs = [ hdrs = [
"end2end_tests.h",
"fixtures/h2_oauth2_common.h", "fixtures/h2_oauth2_common.h",
"fixtures/h2_ssl_cred_reload_fixture.h", "fixtures/h2_ssl_cred_reload_fixture.h",
"fixtures/h2_ssl_tls_common.h", "fixtures/h2_ssl_tls_common.h",
@ -112,14 +147,17 @@ grpc_cc_library(
"fixtures/local_util.h", "fixtures/local_util.h",
"fixtures/secure_fixture.h", "fixtures/secure_fixture.h",
"fixtures/sockpair_fixture.h", "fixtures/sockpair_fixture.h",
"tests/cancel_test_helpers.h",
], ],
external_deps = [ external_deps = [
"absl/status", "absl/status",
"absl/status:statusor", "absl/status:statusor",
"absl/strings", "absl/strings",
"gtest",
], ],
language = "C++", language = "C++",
deps = [ deps = [
"end2end_test_lib",
"//:config", "//:config",
"//:exec_ctx", "//:exec_ctx",
"//:gpr", "//: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( grpc_cc_test(
name = "bad_server_response_test", name = "bad_server_response_test",
srcs = ["bad_server_response_test.cc"], srcs = ["bad_server_response_test.cc"],
@ -267,8 +461,6 @@ grpc_cc_test(
], ],
) )
grpc_end2end_tests()
grpc_cc_test( grpc_cc_test(
name = "h2_ssl_cert_test", name = "h2_ssl_cert_test",
srcs = [ srcs = [
@ -276,21 +468,29 @@ grpc_cc_test(
"h2_ssl_cert_test.cc", "h2_ssl_cert_test.cc",
], ],
external_deps = [ external_deps = [
"absl/memory",
"absl/strings",
"absl/types:optional", "absl/types:optional",
"absl/types:variant",
"gtest", "gtest",
"libcrypto", "libcrypto",
], ],
language = "C++", language = "C++",
deps = [ deps = [
"cq_verifier", "cq_verifier",
"end2end_test_lib",
"fixture_support", "fixture_support",
"ssl_test_data", "ssl_test_data",
"//:config_vars", "//:config_vars",
"//:debug_location",
"//:gpr", "//:gpr",
"//:grpc", "//:grpc",
"//:grpc_public_hdrs", "//:grpc_public_hdrs",
"//:grpc_security_base", "//:grpc_security_base",
"//src/core:bitset",
"//src/core:channel_args", "//src/core:channel_args",
"//src/core:slice",
"//src/core:time",
"//test/core/util:grpc_test_util", "//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_format.h"
#include "absl/strings/str_join.h" #include "absl/strings/str_join.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "gtest/gtest.h"
#include <grpc/byte_buffer.h> #include <grpc/byte_buffer.h>
#include <grpc/compression.h> #include <grpc/compression.h>
@ -196,7 +197,9 @@ std::string TagStr(void* tag) {
namespace grpc_core { 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(); } CqVerifier::~CqVerifier() { Verify(); }
@ -209,30 +212,66 @@ std::string CqVerifier::Expectation::ToString() const {
return absl::StrCat("success=", success ? "true" : "false"); return absl::StrCat("success=", success ? "true" : "false");
}, },
[](Maybe) { return std::string("maybe"); }, [](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; std::vector<std::string> expectations;
expectations.reserve(expectations_.size()); expectations.reserve(expectations_.size());
for (const auto& e : expectations_) { for (const auto& e : expectations_) {
expectations.push_back(e.ToString()); 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 { void CqVerifier::FailNoEventReceived(const SourceLocation& location) const {
Crash(absl::StrFormat("[%s:%d] no event received, but expected:%s", fail_(Failure{location, "No event received", ToStrings()});
location.file(), location.line(), ToString().c_str()));
} }
void CqVerifier::FailUnexpectedEvent(grpc_event* ev, void CqVerifier::FailUnexpectedEvent(grpc_event* ev,
const SourceLocation& location) const { const SourceLocation& location) const {
gpr_log(GPR_ERROR, "[%s:%d] cq returned unexpected event: %s", fail_(Failure{location,
location.file(), location.line(), grpc_event_string(ev).c_str()); absl::StrCat("Unexpected event: ", grpc_event_string(ev)),
Crash(absl::StrFormat("expected tags:\n%s", ToString().c_str())); 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) { void CqVerifier::Verify(Duration timeout, SourceLocation location) {
const gpr_timespec deadline = const gpr_timespec deadline =
grpc_timeout_milliseconds_to_deadline(timeout.millis()); grpc_timeout_milliseconds_to_deadline(timeout.millis());
@ -254,6 +293,14 @@ void CqVerifier::Verify(Duration timeout, SourceLocation location) {
[ev](AnyStatus a) { [ev](AnyStatus a) {
if (a.result != nullptr) *a.result = ev.success; if (a.result != nullptr) *a.result = ev.success;
return true; return true;
},
[ev](const PerformAction& action) {
action.action(ev.success);
return true;
},
[ev](const MaybePerformAction& action) {
action.action(ev.success);
return true;
}); });
if (!expected) { if (!expected) {
FailUnexpectedEvent(&ev, location); FailUnexpectedEvent(&ev, location);
@ -267,16 +314,14 @@ void CqVerifier::Verify(Duration timeout, SourceLocation location) {
} }
expectations_.erase( expectations_.erase(
std::remove_if(expectations_.begin(), expectations_.end(), std::remove_if(expectations_.begin(), expectations_.end(),
[](const Expectation& e) { [](const Expectation& e) { return IsMaybe(e.result); }),
return absl::holds_alternative<Maybe>(e.result);
}),
expectations_.end()); expectations_.end());
if (!expectations_.empty()) FailNoEventReceived(location); if (!expectations_.empty()) FailNoEventReceived(location);
} }
bool CqVerifier::AllMaybes() const { bool CqVerifier::AllMaybes() const {
for (const auto& e : expectations_) { for (const auto& e : expectations_) {
if (!absl::holds_alternative<Maybe>(e.result)) return false; if (!IsMaybe(e.result)) return false;
} }
return true; return true;
} }
@ -293,7 +338,7 @@ void CqVerifier::VerifyEmpty(Duration timeout, SourceLocation location) {
void CqVerifier::Expect(void* tag, ExpectedResult result, void CqVerifier::Expect(void* tag, ExpectedResult result,
SourceLocation location) { SourceLocation location) {
expectations_.push_back(Expectation{location, tag, result}); expectations_.push_back(Expectation{location, tag, std::move(result)});
} }
} // namespace grpc_core } // namespace grpc_core

@ -21,9 +21,11 @@
#include <stdint.h> #include <stdint.h>
#include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/types/variant.h" #include "absl/types/variant.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
@ -48,10 +50,34 @@ class CqVerifier {
struct AnyStatus { struct AnyStatus {
bool* result = nullptr; 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();
CqVerifier(const CqVerifier&) = delete; CqVerifier(const CqVerifier&) = delete;
@ -74,6 +100,7 @@ class CqVerifier {
SourceLocation location = SourceLocation()); SourceLocation location = SourceLocation());
std::string ToString() const; std::string ToString() const;
std::vector<std::string> ToStrings() const;
static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); } static void* tag(intptr_t t) { return reinterpret_cast<void*>(t); }
@ -93,6 +120,7 @@ class CqVerifier {
grpc_completion_queue* const cq_; grpc_completion_queue* const cq_;
std::vector<Expectation> expectations_; std::vector<Expectation> expectations_;
mutable absl::AnyInvocable<void(Failure)> fail_;
}; };
} // namespace grpc_core } // 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 #ifndef GRPC_TEST_CORE_END2END_END2END_TESTS_H
#define GRPC_TEST_CORE_END2END_END2END_TESTS_H #define GRPC_TEST_CORE_END2END_END2END_TESTS_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <algorithm>
#include <functional> #include <functional>
#include <initializer_list>
#include <memory> #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/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/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/channel/channel_args.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" #include "test/core/util/test_config.h"
// Test feature flags. // 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 #define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2
// Feature mask supports call credentials with a minimum security level of // Feature mask supports call credentials with a minimum security level of
// GRPC_PRIVACY_AND_INTEGRITY. // GRPC_PRIVACY_AND_INTEGRITY.
@ -42,12 +68,17 @@
#define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE 8 #define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE 8
#define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING 16 #define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING 16
#define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL 32 #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_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" #define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"
namespace grpc_core {
class CoreTestFixture { class CoreTestFixture {
public: public:
virtual ~CoreTestFixture() { virtual ~CoreTestFixture() {
@ -62,12 +93,12 @@ class CoreTestFixture {
grpc_server* server() { return server_; } grpc_server* server() { return server_; }
grpc_channel* client() { return client_; } grpc_channel* client() { return client_; }
void InitServer(const grpc_core::ChannelArgs& args) { void InitServer(const ChannelArgs& args) {
if (server_ != nullptr) ShutdownServer(); if (server_ != nullptr) ShutdownServer();
server_ = MakeServer(args); server_ = MakeServer(args);
GPR_ASSERT(server_ != nullptr); GPR_ASSERT(server_ != nullptr);
} }
void InitClient(const grpc_core::ChannelArgs& args) { void InitClient(const ChannelArgs& args) {
if (client_ != nullptr) ShutdownClient(); if (client_ != nullptr) ShutdownClient();
client_ = MakeClient(args); client_ = MakeClient(args);
GPR_ASSERT(client_ != nullptr); GPR_ASSERT(client_ != nullptr);
@ -96,14 +127,14 @@ class CoreTestFixture {
client_ = nullptr; client_ = nullptr;
} }
virtual grpc_server* MakeServer(const ChannelArgs& args) = 0;
virtual grpc_channel* MakeClient(const ChannelArgs& args) = 0;
protected: protected:
void SetServer(grpc_server* server); void SetServer(grpc_server* server);
void SetClient(grpc_channel* client); void SetClient(grpc_channel* client);
private: private:
virtual grpc_server* MakeServer(const grpc_core::ChannelArgs& args) = 0;
virtual grpc_channel* MakeClient(const grpc_core::ChannelArgs& args) = 0;
void DrainCq() { void DrainCq() {
grpc_event ev; grpc_event ev;
do { do {
@ -117,6 +148,12 @@ class CoreTestFixture {
grpc_channel* client_ = nullptr; 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 { struct CoreTestConfiguration {
// A descriptive name for this test fixture. // A descriptive name for this test fixture.
const char* name; const char* name;
@ -130,23 +167,584 @@ struct CoreTestConfiguration {
const char* overridden_call_host; const char* overridden_call_host;
std::function<std::unique_ptr<CoreTestFixture>( std::function<std::unique_ptr<CoreTestFixture>(
const grpc_core::ChannelArgs& client_args, const ChannelArgs& client_args, const ChannelArgs& server_args)>
const grpc_core::ChannelArgs& server_args)>
create_fixture; create_fixture;
}; };
void grpc_end2end_tests_pre_init(void); // Base class for e2e tests.
void grpc_end2end_tests(int argc, char** argv, //
const CoreTestConfiguration& config); // 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, } // namespace grpc_core
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);
void validate_host_override_string(const char* pattern, grpc_slice str, // If this test fixture is being run under minstack, skip the test.
const CoreTestConfiguration& config); #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 #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 = static const uint32_t kH2TLSFeatureMask =
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL | FEATURE_MASK_IS_HTTP2;
FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER;
#endif // GRPC_TEST_CORE_END2END_FIXTURES_H2_TLS_COMMON_H #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 "src/core/lib/channel/channel_args.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
class InprocFixture : public CoreTestFixture { class InprocFixture : public grpc_core::CoreTestFixture {
private: private:
grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override { grpc_server* MakeServer(const grpc_core::ChannelArgs& args) override {
auto* server = grpc_server_create(args.ToC().get(), nullptr); auto* server = grpc_server_create(args.ToC().get(), nullptr);

@ -27,7 +27,7 @@
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
class LocalTestFixture final : public CoreTestFixture { class LocalTestFixture final : public grpc_core::CoreTestFixture {
public: public:
LocalTestFixture(std::string localaddr, grpc_local_connect_type type); 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 // Base class for a fixture that just needs to select cred types (or mutate
// client/server channel args). // client/server channel args).
class SecureFixture : public CoreTestFixture { class SecureFixture : public grpc_core::CoreTestFixture {
public: public:
explicit SecureFixture(std::string localaddr = grpc_core::JoinHostPort( explicit SecureFixture(std::string localaddr = grpc_core::JoinHostPort(
"localhost", grpc_pick_unused_port_or_die())) "localhost", grpc_pick_unused_port_or_die()))

@ -15,8 +15,11 @@
#ifndef GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H #ifndef GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H
#define 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/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/status.h> #include <grpc/status.h>
@ -40,32 +43,44 @@
#include "src/core/lib/transport/transport_fwd.h" #include "src/core/lib/transport/transport_fwd.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
namespace grpc_core {
class SockpairFixture : public CoreTestFixture { class SockpairFixture : public CoreTestFixture {
public: 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())) {} : ep_(grpc_iomgr_create_endpoint_pair("fixture", ep_args.ToC().get())) {}
private: ~SockpairFixture() override {
virtual grpc_core::ChannelArgs MutateClientArgs(grpc_core::ChannelArgs args) { ExecCtx exec_ctx;
return args; if (ep_.client != nullptr) {
} grpc_endpoint_shutdown(ep_.client, absl::InternalError("done"));
virtual grpc_core::ChannelArgs MutateServerArgs(grpc_core::ChannelArgs args) { grpc_endpoint_destroy(ep_.client);
return args; }
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); auto args = MutateServerArgs(in_args);
grpc_core::ExecCtx exec_ctx; ExecCtx exec_ctx;
grpc_transport* transport; grpc_transport* transport;
auto* server = grpc_server_create(args.ToC().get(), nullptr); auto* server = grpc_server_create(args.ToC().get(), nullptr);
grpc_server_register_completion_queue(server, cq(), nullptr); grpc_server_register_completion_queue(server, cq(), nullptr);
grpc_server_start(server); grpc_server_start(server);
auto server_channel_args = grpc_core::CoreConfiguration::Get() auto server_channel_args = CoreConfiguration::Get()
.channel_args_preconditioning() .channel_args_preconditioning()
.PreconditionChannelArgs(args.ToC().get()); .PreconditionChannelArgs(args.ToC().get());
transport = auto* server_endpoint = std::exchange(ep_.server, nullptr);
grpc_create_chttp2_transport(server_channel_args, ep_.server, false); EXPECT_NE(server_endpoint, nullptr);
grpc_endpoint_add_to_pollset(ep_.server, grpc_cq_pollset(cq())); transport = grpc_create_chttp2_transport(server_channel_args,
grpc_core::Server* core_server = grpc_core::Server::FromC(server); 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( grpc_error_handle error = core_server->SetupTransport(
transport, nullptr, core_server->channel_args(), nullptr); transport, nullptr, core_server->channel_args(), nullptr);
if (error.ok()) { if (error.ok()) {
@ -75,9 +90,9 @@ class SockpairFixture : public CoreTestFixture {
} }
return server; return server;
} }
grpc_channel* MakeClient(const grpc_core::ChannelArgs& in_args) override { grpc_channel* MakeClient(const ChannelArgs& in_args) override {
grpc_core::ExecCtx exec_ctx; ExecCtx exec_ctx;
auto args = grpc_core::CoreConfiguration::Get() auto args = CoreConfiguration::Get()
.channel_args_preconditioning() .channel_args_preconditioning()
.PreconditionChannelArgs( .PreconditionChannelArgs(
MutateClientArgs(in_args) MutateClientArgs(in_args)
@ -85,9 +100,11 @@ class SockpairFixture : public CoreTestFixture {
.ToC() .ToC()
.get()); .get());
grpc_transport* transport; grpc_transport* transport;
transport = grpc_create_chttp2_transport(args, ep_.client, true); auto* client_endpoint = std::exchange(ep_.client, nullptr);
auto channel = grpc_core::Channel::Create( EXPECT_NE(client_endpoint, nullptr);
"socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport); transport = grpc_create_chttp2_transport(args, client_endpoint, true);
auto channel = Channel::Create("socketpair-target", args,
GRPC_CLIENT_DIRECT_CHANNEL, transport);
grpc_channel* client; grpc_channel* client;
if (channel.ok()) { if (channel.ok()) {
client = channel->release()->c_ptr(); client = channel->release()->c_ptr();
@ -104,5 +121,6 @@ class SockpairFixture : public CoreTestFixture {
grpc_endpoint_pair ep_; grpc_endpoint_pair ep_;
}; };
} // namespace grpc_core
#endif // GRPC_TEST_CORE_END2END_FIXTURES_SOCKPAIR_FIXTURE_H #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) \ #define SSL_TEST(request_type, cert_type, result) \
{ \ { \
{TEST_NAME(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, \ FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL, \
"foo.test.google.fr", TestFixture::MakeFactory(request_type, cert_type)}, \ "foo.test.google.fr", TestFixture::MakeFactory(request_type, cert_type)}, \
result \ result \
@ -150,7 +149,7 @@ typedef enum { SUCCESS, FAIL } test_result;
// All test configurations // All test configurations
struct CoreTestConfigWrapper { struct CoreTestConfigWrapper {
CoreTestConfiguration config; grpc_core::CoreTestConfiguration config;
test_result result; test_result result;
}; };
@ -194,7 +193,7 @@ static CoreTestConfigWrapper configs[] = {
BAD_CERT_PAIR, FAIL), BAD_CERT_PAIR, FAIL),
}; };
static void simple_request_body(CoreTestFixture* f, static void simple_request_body(grpc_core::CoreTestFixture* f,
test_result expected_result) { test_result expected_result) {
grpc_call* c; grpc_call* c;
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
@ -239,7 +238,7 @@ class H2SslCertTest : public ::testing::TestWithParam<CoreTestConfigWrapper> {
} }
void TearDown() override { fixture_.reset(); } void TearDown() override { fixture_.reset(); }
std::unique_ptr<CoreTestFixture> fixture_; std::unique_ptr<grpc_core::CoreTestFixture> fixture_;
}; };
TEST_P(H2SslCertTest, SimpleRequestBody) { 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 "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.h"
#include "src/core/lib/gprpp/time.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/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
#define MAX_PING_STRIKES 2 #define MAX_PING_STRIKES 2
// Send more pings than server allows to trigger server's GOAWAY. namespace grpc_core {
static void test_bad_ping(const CoreTestConfiguration& config) { namespace {
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();
// 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: // Send too many pings to the server to trigger the punishment:
// The first ping will let server mark its last_recv time. Afterwards, each // 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 // 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. // needed here.
int i; int i;
for (i = 1; i <= MAX_PING_STRIKES + 2; i++) { for (i = 1; i <= MAX_PING_STRIKES + 2; i++) {
grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(200 + i), PingServerFromClient(200 + i);
nullptr); Expect(200 + i, true);
cqv.Expect(grpc_core::CqVerifier::tag(200 + i), true);
if (i == MAX_PING_STRIKES + 2) { if (i == MAX_PING_STRIKES + 2) {
cqv.Expect(grpc_core::CqVerifier::tag(1), true); Expect(1, true);
} }
cqv.Verify(); Step();
} }
CoreEnd2endTest::IncomingCloseOnServer client_close;
memset(ops, 0, sizeof(ops)); s.NewBatch(102)
op = ops; .SendInitialMetadata({})
op->op = GRPC_OP_SEND_INITIAL_METADATA; .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
op->data.send_initial_metadata.count = 0; .RecvCloseOnServer(client_close);
op->flags = 0; Expect(102, true);
op->reserved = nullptr; Step();
op++; ShutdownServerAndNotify(103);
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; Expect(103, true);
op->data.send_status_from_server.trailing_metadata_count = 0; Step();
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);
// The connection should be closed immediately after the misbehaved pings, // The connection should be closed immediately after the misbehaved pings,
// the in-progress RPC should fail. // the in-progress RPC should fail.
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAVAILABLE);
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); EXPECT_EQ(s.method(), "/foo");
GPR_ASSERT(was_cancelled == 1); EXPECT_TRUE(client_close.was_cancelled());
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);
} }
// Try sending more pings than server allows, but server should be fine because // Try sending more pings than server allows, but server should be fine because
// max_pings_without_data should limit pings sent out on wire. // max_pings_without_data should limit pings sent out on wire.
static void test_pings_without_data(const CoreTestConfiguration& config) { TEST_P(RetryHttp2Test, PingsWithoutData) {
auto f =
config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs());
grpc_core::CqVerifier cqv(f->cq());
// Only allow MAX_PING_STRIKES pings without data (DATA/HEADERS/WINDOW_UPDATE) // Only allow MAX_PING_STRIKES pings without data (DATA/HEADERS/WINDOW_UPDATE)
// so that the transport will throttle the excess pings. // so that the transport will throttle the excess pings.
auto client_args = InitClient(ChannelArgs()
grpc_core::ChannelArgs() .Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, MAX_PING_STRIKES)
.Set(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA, MAX_PING_STRIKES) .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0));
.Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); InitServer(ChannelArgs()
auto server_args = .Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS,
grpc_core::ChannelArgs() Duration::Minutes(5).millis())
.Set(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, .Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES)
grpc_core::Duration::Minutes(5).millis()) .Set(GRPC_ARG_HTTP2_BDP_PROBE, 0));
.Set(GRPC_ARG_HTTP2_MAX_PING_STRIKES, MAX_PING_STRIKES) auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create();
.Set(GRPC_ARG_HTTP2_BDP_PROBE, 0); CoreEnd2endTest::IncomingStatusOnClient server_status;
CoreEnd2endTest::IncomingMetadata server_initial_metadata;
f->InitClient(client_args); c.NewBatch(1)
f->InitServer(server_args); .SendInitialMetadata({})
.SendCloseFromClient()
grpc_call* c; .RecvInitialMetadata(server_initial_metadata)
grpc_call* s; .RecvStatusOnClient(server_status);
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); auto s = RequestCall(101);
grpc_op ops[6]; Expect(101, true);
grpc_op* op; Step();
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();
// Send too many pings to the server similar to the previous test case. // 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 // 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. // MAX_PING_STRIKES will actually be sent and the rpc will still succeed.
int i; int i;
for (i = 1; i <= MAX_PING_STRIKES + 2; i++) { for (i = 1; i <= MAX_PING_STRIKES + 2; i++) {
grpc_channel_ping(f->client(), f->cq(), grpc_core::CqVerifier::tag(200 + i), PingServerFromClient(200 + i);
nullptr);
if (i <= MAX_PING_STRIKES) { if (i <= MAX_PING_STRIKES) {
cqv.Expect(grpc_core::CqVerifier::tag(200 + i), true); Expect(200 + i, true);
} }
cqv.Verify(); Step();
} }
CoreEnd2endTest::IncomingCloseOnServer client_close;
memset(ops, 0, sizeof(ops)); s.NewBatch(102)
op = ops; .SendInitialMetadata({})
op->op = GRPC_OP_SEND_INITIAL_METADATA; .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
op->data.send_initial_metadata.count = 0; .RecvCloseOnServer(client_close);
op->flags = 0; Expect(102, true);
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);
// Client call should return. // Client call should return.
cqv.Expect(grpc_core::CqVerifier::tag(1), true); Expect(1, true);
cqv.Verify(); Step();
ShutdownServerAndNotify(103);
grpc_server_shutdown_and_notify(f->server(), f->cq(), Expect(103, true);
grpc_core::CqVerifier::tag(0xdead));
cqv.Expect(grpc_core::CqVerifier::tag(0xdead), true);
// Also expect the previously blocked pings to complete with an error // Also expect the previously blocked pings to complete with an error
cqv.Expect(grpc_core::CqVerifier::tag(200 + MAX_PING_STRIKES + 1), false); Expect(200 + MAX_PING_STRIKES + 1, false);
cqv.Expect(grpc_core::CqVerifier::tag(200 + MAX_PING_STRIKES + 2), false); Expect(200 + MAX_PING_STRIKES + 2, false);
Step();
cqv.Verify();
grpc_call_unref(s);
// The rpc should be successful. // The rpc should be successful.
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); EXPECT_EQ(s.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);
} }
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/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.h"
#include "src/core/lib/channel/channel_args_preconditioning.h" #include "src/core/lib/gprpp/time.h"
#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/slice/slice.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name,
grpc_channel_args* client_args, grpc_channel_args* server_args) { static void BinaryMetadata(CoreEnd2endTest& test, bool server_true_binary,
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); bool client_true_binary) {
client_args = test.InitServer(
const_cast<grpc_channel_args*>(grpc_core::CoreConfiguration::Get() ChannelArgs().Set(GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, server_true_binary));
.channel_args_preconditioning() test.InitClient(
.PreconditionChannelArgs(client_args) ChannelArgs().Set(GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY, client_true_binary));
.ToC()
.release()); auto key1_payload = RandomBinarySlice(32);
server_args = auto key2_payload = RandomBinarySlice(18);
const_cast<grpc_channel_args*>(grpc_core::CoreConfiguration::Get() auto key3_payload = RandomBinarySlice(17);
.channel_args_preconditioning() auto key4_payload = RandomBinarySlice(68);
.PreconditionChannelArgs(server_args) auto key5_payload = RandomBinarySlice(33);
.ToC() auto key6_payload = RandomBinarySlice(2);
.release()); auto request_payload = RandomBinarySlice(7);
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), auto response_payload = RandomBinarySlice(9);
grpc_core::ChannelArgs::FromC(server_args)); auto status_string = RandomBinarySlice(256);
f->InitServer(grpc_core::ChannelArgs::FromC(server_args));
f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
grpc_channel_args_destroy(client_args); CoreEnd2endTest::IncomingMetadata server_initial_md;
grpc_channel_args_destroy(server_args); CoreEnd2endTest::IncomingMessage server_message;
return f; 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. TEST_P(CoreEnd2endTest, BinaryMetadataServerTrueBinaryClientHttp2Fallback) {
static void test_request_response_with_metadata_and_payload( BinaryMetadata(*this, true, false);
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);
grpc_call_unref(c); TEST_P(CoreEnd2endTest, BinaryMetadataServerHttp2FallbackClientTrueBinary) {
grpc_call_unref(s); BinaryMetadata(*this, false, true);
}
grpc_byte_buffer_destroy(request_payload); TEST_P(CoreEnd2endTest, BinaryMetadataServerTrueBinaryClientTrueBinary) {
grpc_byte_buffer_destroy(response_payload); BinaryMetadata(*this, true, true);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
} }
void binary_metadata(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, BinaryMetadataServerHttp2FallbackClientHttp2Fallback) {
test_request_response_with_metadata_and_payload(config); 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 <memory>
#include <grpc/byte_buffer.h> #include "absl/types/optional.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/grpc_security.h> #include <grpc/grpc_security.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.h> #include <grpc/status.h>
#include <grpc/support/log.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.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/security/credentials/credentials.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/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static const char iam_token[] = "token"; namespace grpc_core {
static const char iam_selector[] = "selector"; namespace {
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";
typedef enum { NONE, OVERRIDE, DESTROY, FAIL } override_mode; const char iam_token[] = "token";
const char iam_selector[] = "selector";
static std::unique_ptr<CoreTestFixture> begin_test( const char overridden_iam_token[] = "overridden_token";
const CoreTestConfiguration& config, const char* test_name, const char overridden_iam_selector[] = "overridden_selector";
bool use_secure_call_creds, int fail_server_auth_check) { const char fake_md_key[] = "fake_key";
gpr_log(GPR_INFO, "Running test: %s%s/%s", test_name, const char fake_md_value[] = "fake_value";
use_secure_call_creds ? "_with_secure_call_creds" const char overridden_fake_md_key[] = "overridden_fake_key";
: "_with_insecure_call_creds", const char overridden_fake_md_value[] = "overridden_fake_value";
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;
}
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; const grpc_auth_property* p;
grpc_auth_property_iterator it; grpc_auth_property_iterator it;
gpr_log(GPR_INFO, "%s peer:", is_client ? "client" : "server"); 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( void TestRequestResponseWithPayloadAndCallCreds(CoreEnd2endTest& test,
const char* test_name, const CoreTestConfiguration& config, bool use_secure_call_creds) {
override_mode mode, bool use_secure_call_creds) { auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
grpc_call* c = nullptr; grpc_call_credentials* creds;
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);
if (use_secure_call_creds) { if (use_secure_call_creds) {
creds = creds =
grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr); grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
} else { } else {
creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value); creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value);
} }
GPR_ASSERT(creds != nullptr); EXPECT_NE(creds, nullptr);
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); c.SetCredentials(creds);
switch (mode) { CoreEnd2endTest::IncomingMetadata server_initial_metadata;
case NONE: CoreEnd2endTest::IncomingMessage server_message;
break; CoreEnd2endTest::IncomingStatusOnClient server_status;
case OVERRIDE: c.NewBatch(1)
grpc_call_credentials_release(creds); .SendInitialMetadata({})
if (use_secure_call_creds) { .SendMessage("hello world")
creds = grpc_google_iam_credentials_create( .SendCloseFromClient()
overridden_iam_token, overridden_iam_selector, nullptr); .RecvInitialMetadata(server_initial_metadata)
} else { .RecvMessage(server_message)
creds = grpc_md_only_test_credentials_create(overridden_fake_md_key, .RecvStatusOnClient(server_status);
overridden_fake_md_value); auto s = test.RequestCall(101);
} test.Expect(101, true);
GPR_ASSERT(creds != nullptr); test.Step();
GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); PrintAuthContext(false, s.GetAuthContext().get());
break; PrintAuthContext(true, c.GetAuthContext().get());
case DESTROY: // Cannot set creds on the server call object.
GPR_ASSERT(grpc_call_set_credentials(c, nullptr) == GRPC_CALL_OK); EXPECT_NE(grpc_call_set_credentials(s.c_call(), nullptr), GRPC_CALL_OK);
break; CoreEnd2endTest::IncomingMessage client_message;
case FAIL: s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message);
// Do nothing test.Expect(102, true);
break; 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) { void TestRequestResponseWithPayloadAndOverriddenCallCreds(
// Expect the call to fail since the channel credentials did not satisfy the CoreEnd2endTest& test, bool use_secure_call_creds) {
// minimum security level requirements. auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
cqv.Expect(grpc_core::CqVerifier::tag(1), true); grpc_call_credentials* creds;
cqv.Verify(); if (use_secure_call_creds) {
GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); creds =
grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
} else { } else {
error = grpc_server_request_call(f->server(), &s, &call_details, creds = grpc_md_only_test_credentials_create(fake_md_key, fake_md_value);
&request_metadata_recv, f->cq(), f->cq(), }
grpc_core::CqVerifier::tag(101)); EXPECT_NE(creds, nullptr);
GPR_ASSERT(GRPC_CALL_OK == error); c.SetCredentials(creds);
cqv.Expect(grpc_core::CqVerifier::tag(101), true); if (use_secure_call_creds) {
cqv.Verify(); creds = grpc_google_iam_credentials_create(
server_auth_context = grpc_call_auth_context(s); overridden_iam_token, overridden_iam_selector, nullptr);
GPR_ASSERT(server_auth_context != nullptr); } else {
print_auth_context(0, server_auth_context); creds = grpc_md_only_test_credentials_create(overridden_fake_md_key,
grpc_auth_context_release(server_auth_context); overridden_fake_md_value);
}
client_auth_context = grpc_call_auth_context(c); c.SetCredentials(creds);
GPR_ASSERT(client_auth_context != nullptr); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
print_auth_context(1, client_auth_context); CoreEnd2endTest::IncomingMessage server_message;
grpc_auth_context_release(client_auth_context); CoreEnd2endTest::IncomingStatusOnClient server_status;
c.NewBatch(1)
// Cannot set creds on the server call object. .SendInitialMetadata({})
GPR_ASSERT(grpc_call_set_credentials(s, nullptr) != GRPC_CALL_OK); .SendMessage("hello world")
.SendCloseFromClient()
memset(ops, 0, sizeof(ops)); .RecvInitialMetadata(server_initial_metadata)
op = ops; .RecvMessage(server_message)
op->op = GRPC_OP_SEND_INITIAL_METADATA; .RecvStatusOnClient(server_status);
op->data.send_initial_metadata.count = 0; auto s = test.RequestCall(101);
op->flags = 0; test.Expect(101, true);
op->reserved = nullptr; test.Step();
op++; PrintAuthContext(false, s.GetAuthContext().get());
op->op = GRPC_OP_RECV_MESSAGE; PrintAuthContext(true, c.GetAuthContext().get());
op->data.recv_message.recv_message = &request_payload_recv; // Cannot set creds on the server call object.
op->flags = 0; EXPECT_NE(grpc_call_set_credentials(s.c_call(), nullptr), GRPC_CALL_OK);
op->reserved = nullptr; CoreEnd2endTest::IncomingMessage client_message;
op++; s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message);
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), test.Expect(102, true);
grpc_core::CqVerifier::tag(102), nullptr); test.Step();
GPR_ASSERT(GRPC_CALL_OK == error); CoreEnd2endTest::IncomingCloseOnServer client_close;
s.NewBatch(103)
cqv.Expect(grpc_core::CqVerifier::tag(102), true); .RecvCloseOnServer(client_close)
cqv.Verify(); .SendMessage("hello you")
.SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
memset(ops, 0, sizeof(ops)); test.Expect(103, true);
op = ops; test.Expect(1, true);
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; test.Step();
op->data.recv_close_on_server.cancelled = &was_cancelled; EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
op->flags = 0; EXPECT_EQ(server_status.message(), "xyz");
op->reserved = nullptr; EXPECT_EQ(s.method(), "/foo");
op++; EXPECT_FALSE(client_close.was_cancelled());
op->op = GRPC_OP_SEND_MESSAGE; EXPECT_EQ(client_message.payload(), "hello world");
op->data.send_message.send_message = response_payload; EXPECT_EQ(server_message.payload(), "hello you");
op->flags = 0; if (use_secure_call_creds) {
op->reserved = nullptr; EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY),
op++; overridden_iam_token);
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; EXPECT_EQ(s.GetInitialMetadata(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY),
op->data.send_status_from_server.trailing_metadata_count = 0; overridden_iam_selector);
op->data.send_status_from_server.status = GRPC_STATUS_OK; } else {
grpc_slice status_details = grpc_slice_from_static_string("xyz"); EXPECT_EQ(s.GetInitialMetadata(overridden_fake_md_key),
op->data.send_status_from_server.status_details = &status_details; overridden_fake_md_value);
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);
} }
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( void TestRequestResponseWithPayloadAndDeletedCallCreds(
const CoreTestConfiguration& config, bool use_secure_call_creds) { CoreEnd2endTest& test, bool use_secure_call_creds) {
request_response_with_payload_and_call_creds( auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
"test_request_response_with_payload_and_call_creds", config, NONE, grpc_call_credentials* creds;
use_secure_call_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( TEST_P(PerCallCredsOnInsecureTest, RequestWithServerRejectingClientCreds) {
const CoreTestConfiguration& config, bool use_secure_call_creds) { InitClient(ChannelArgs());
request_response_with_payload_and_call_creds( InitServer(ChannelArgs().Set(FAIL_AUTH_CHECK_SERVER_ARG_NAME, true));
"test_request_response_with_payload_and_overridden_call_creds", config, auto c = NewClientCall("/foo").Timeout(Duration::Seconds(10)).Create();
OVERRIDE, use_secure_call_creds); 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( TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndCallCreds) {
const CoreTestConfiguration& config, bool use_secure_call_creds) { TestRequestResponseWithPayloadAndCallCreds(*this, true);
request_response_with_payload_and_call_creds(
"test_request_response_with_payload_and_deleted_call_creds", config,
DESTROY, use_secure_call_creds);
} }
static void test_request_response_with_payload_fail_to_send_call_creds( TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndOverriddenCallCreds) {
const CoreTestConfiguration& config, bool use_secure_call_creds) { TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, true);
request_response_with_payload_and_call_creds(
"test_request_response_with_payload_fail_to_send_call_creds", config,
FAIL, use_secure_call_creds);
} }
static void test_request_with_server_rejecting_client_creds( TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndDeletedCallCreds) {
const CoreTestConfiguration& config) { TestRequestResponseWithPayloadAndDeletedCallCreds(*this, true);
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);
memset(ops, 0, sizeof(ops)); TEST_P(PerCallCredsTest, RequestResponseWithPayloadAndInsecureCallCreds) {
op = ops; TestRequestResponseWithPayloadAndCallCreds(*this, false);
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);
cqv.Expect(grpc_core::CqVerifier::tag(1), true); TEST_P(PerCallCredsTest,
cqv.Verify(); RequestResponseWithPayloadAndOverriddenInsecureCallCreds) {
TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, false);
}
GPR_ASSERT(status == GRPC_STATUS_UNAUTHENTICATED); TEST_P(PerCallCredsTest,
RequestResponseWithPayloadAndDeletedInsecureCallCreds) {
TestRequestResponseWithPayloadAndDeletedCallCreds(*this, false);
}
grpc_metadata_array_destroy(&initial_metadata_recv); TEST_P(PerCallCredsOnInsecureTest,
grpc_metadata_array_destroy(&trailing_metadata_recv); RequestResponseWithPayloadAndInsecureCallCreds) {
grpc_metadata_array_destroy(&request_metadata_recv); TestRequestResponseWithPayloadAndCallCreds(*this, false);
grpc_call_details_destroy(&call_details); }
grpc_byte_buffer_destroy(request_payload); TEST_P(PerCallCredsOnInsecureTest,
grpc_byte_buffer_destroy(response_payload_recv); RequestResponseWithPayloadAndOverriddenInsecureCallCreds) {
grpc_slice_unref(details); TestRequestResponseWithPayloadAndOverriddenCallCreds(*this, false);
}
grpc_call_unref(c); TEST_P(PerCallCredsOnInsecureTest,
RequestResponseWithPayloadAndDeletedInsecureCallCreds) {
TestRequestResponseWithPayloadAndDeletedCallCreds(*this, false);
} }
void call_creds(const CoreTestConfiguration& config) { TEST_P(PerCallCredsOnInsecureTest, FailToSendCallCreds) {
// Test fixtures that support call credentials with a minimum security level auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
// of GRPC_PRIVACY_AND_INTEGRITY grpc_call_credentials* creds;
if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS) { creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
test_request_response_with_payload_and_call_creds(config, true); EXPECT_NE(creds, nullptr);
test_request_response_with_payload_and_overridden_call_creds(config, true); c.SetCredentials(creds);
test_request_response_with_payload_and_deleted_call_creds(config, true); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
} CoreEnd2endTest::IncomingMessage server_message;
// Test that fixtures that support call credentials with a minimum security CoreEnd2endTest::IncomingStatusOnClient server_status;
// level of GRPC_SECURITY_NONE cannot send call credentials that require c.NewBatch(1)
// higher security level .SendInitialMetadata({})
if (config.feature_mask & .SendMessage("hello world")
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE) { .SendCloseFromClient()
test_request_response_with_payload_fail_to_send_call_creds(config, true); .RecvInitialMetadata(server_initial_metadata)
} .RecvMessage(server_message)
// Fixtures that support sending call credentials should be able to send call .RecvStatusOnClient(server_status);
// credentials of security level GRPC_SECURITY_NONE. // Expect the call to fail since the channel credentials did not satisfy the
if (config.feature_mask & FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS || // minimum security level requirements.
config.feature_mask & Expect(1, true);
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS_LEVEL_INSECURE) { Step();
test_request_response_with_payload_and_call_creds(config, false); EXPECT_EQ(server_status.status(), GRPC_STATUS_UNAUTHENTICATED);
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);
}
} }
void call_creds_pre_init(void) {} } // namespace
} // namespace grpc_core

@ -16,162 +16,54 @@
// //
// //
#include <string.h> #include "absl/types/optional.h"
#include "gtest/gtest.h"
#include <functional>
#include <memory>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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/channel/channel_args.h"
#include "test/core/end2end/cq_verifier.h" #include "src/core/lib/gprpp/time.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/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) { namespace grpc_core {
test_invoke_simple_request(config); 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 <memory>
#include <string>
#include <grpc/byte_buffer.h> #include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.h"
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
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;
}
// Cancel after accept, no payload // Cancel after accept, no payload
static void test_cancel_after_accept(const CoreTestConfiguration& config, void CancelAfterAccept(CoreEnd2endTest& test,
cancellation_mode mode, std::unique_ptr<CancellationMode> cancellation_mode,
bool use_service_config) { Duration timeout) {
grpc_op ops[6]; auto c = test.NewClientCall("/service/method").Timeout(timeout).Create();
grpc_op* op; CoreEnd2endTest::IncomingStatusOnClient server_status;
grpc_call* c; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_call* s; CoreEnd2endTest::IncomingMessage server_message;
grpc_metadata_array initial_metadata_recv; c.NewBatch(1)
grpc_metadata_array trailing_metadata_recv; .RecvStatusOnClient(server_status)
grpc_metadata_array request_metadata_recv; .SendInitialMetadata({})
grpc_call_details call_details; .SendMessage(RandomSlice(1024))
grpc_status_code status; .RecvInitialMetadata(server_initial_metadata)
grpc_call_error error; .RecvMessage(server_message);
grpc_slice details; auto s = test.RequestCall(2);
grpc_byte_buffer* request_payload_recv = nullptr; test.Expect(2, true);
grpc_byte_buffer* response_payload_recv = nullptr; test.Step();
grpc_slice request_payload_slice = CoreEnd2endTest::IncomingMessage client_message;
grpc_slice_from_copied_string("hello world"); CoreEnd2endTest::IncomingCloseOnServer client_close;
grpc_slice response_payload_slice = s.NewBatch(3)
grpc_slice_from_copied_string("hello you"); .RecvMessage(client_message)
grpc_byte_buffer* request_payload = .SendInitialMetadata({})
grpc_raw_byte_buffer_create(&request_payload_slice, 1); .SendMessage(RandomSlice(1024))
grpc_byte_buffer* response_payload = .RecvCloseOnServer(client_close);
grpc_raw_byte_buffer_create(&response_payload_slice, 1); cancellation_mode->Apply(c);
int was_cancelled = 2; test.Expect(1, true);
test.Expect(3, true);
grpc_channel_args* args = nullptr; test.Step();
if (use_service_config) { EXPECT_THAT(server_status.status(),
grpc_arg arg; ::testing::AnyOf(cancellation_mode->ExpectedStatus(),
arg.type = GRPC_ARG_STRING; GRPC_STATUS_INTERNAL));
arg.key = const_cast<char*>(GRPC_ARG_SERVICE_CONFIG); EXPECT_TRUE(client_close.was_cancelled());
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);
if (args != nullptr) { TEST_P(CoreEnd2endTest, CancelAfterAccept) {
grpc_core::ExecCtx exec_ctx; CancelAfterAccept(*this, std::make_unique<CancelCancellationMode>(),
grpc_channel_args_destroy(args); Duration::Seconds(5));
}
} }
void cancel_after_accept(const CoreTestConfiguration& config) { TEST_P(CoreDeadlineTest, DeadlineAfterAccept) {
unsigned i; CancelAfterAccept(*this, std::make_unique<DeadlineCancellationMode>(),
Duration::Seconds(5));
}
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { TEST_P(CoreClientChannelTest, DeadlineAfterAcceptWithServiceConfig) {
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && InitServer(ChannelArgs());
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { InitClient(ChannelArgs().Set(
continue; GRPC_ARG_SERVICE_CONFIG,
} "{\n"
test_cancel_after_accept(config, cancellation_modes[i], " \"methodConfig\": [ {\n"
false /* use_service_config */); " \"name\": [\n"
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && " { \"service\": \"service\", \"method\": \"method\" },\n"
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { " { \"service\": \"unused\" }\n"
test_cancel_after_accept(config, cancellation_modes[i], " ],\n"
true /* use_service_config */); " \"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 <memory>
#include <grpc/byte_buffer.h> #include "gmock/gmock.h"
#include <grpc/grpc.h> #include "gtest/gtest.h"
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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/gpr/useful.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
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 after accept with a writes closed, no payload // Cancel after accept with a writes closed, no payload
static void test_cancel_after_accept_and_writes_closed( void CancelAfterClientDone(
const CoreTestConfiguration& config, cancellation_mode mode) { CoreEnd2endTest& test,
grpc_op ops[6]; std::unique_ptr<CancellationMode> cancellation_mode) {
grpc_op* op; auto c = test.NewClientCall("/service/method")
grpc_call* c; .Timeout(Duration::Seconds(5))
grpc_call* s; .Create();
auto f = begin_test(config, "test_cancel_after_accept_and_writes_closed", CoreEnd2endTest::IncomingStatusOnClient server_status;
mode, nullptr, nullptr); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_core::CqVerifier cqv(f->cq()); CoreEnd2endTest::IncomingMessage server_message;
grpc_metadata_array initial_metadata_recv; c.NewBatch(1)
grpc_metadata_array trailing_metadata_recv; .RecvStatusOnClient(server_status)
grpc_metadata_array request_metadata_recv; .SendInitialMetadata({})
grpc_call_details call_details; .SendMessage(RandomSlice(1024))
grpc_status_code status; .RecvInitialMetadata(server_initial_metadata)
grpc_call_error error; .RecvMessage(server_message)
grpc_slice details; .SendCloseFromClient();
grpc_byte_buffer* request_payload_recv = nullptr; auto s = test.RequestCall(2);
grpc_byte_buffer* response_payload_recv = nullptr; test.Expect(2, true);
grpc_slice request_payload_slice = test.Step();
grpc_slice_from_copied_string("hello world"); CoreEnd2endTest::IncomingMessage client_message;
grpc_slice response_payload_slice = CoreEnd2endTest::IncomingCloseOnServer client_close;
grpc_slice_from_copied_string("hello you"); s.NewBatch(3)
grpc_byte_buffer* request_payload = .RecvMessage(client_message)
grpc_raw_byte_buffer_create(&request_payload_slice, 1); .SendInitialMetadata({})
grpc_byte_buffer* response_payload = .SendMessage(RandomSlice(1024))
grpc_raw_byte_buffer_create(&response_payload_slice, 1); .RecvCloseOnServer(client_close);
int was_cancelled = 2; cancellation_mode->Apply(c);
test.Expect(1, true);
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); test.Expect(3, true);
c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, test.Step();
f->cq(), grpc_slice_from_static_string("/foo"), EXPECT_THAT(server_status.status(),
nullptr, deadline, nullptr); ::testing::AnyOf(cancellation_mode->ExpectedStatus(),
GPR_ASSERT(c); GRPC_STATUS_INTERNAL));
EXPECT_TRUE(client_close.was_cancelled());
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 cancel_after_client_done(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, CancelAfterClientDone) {
unsigned i; CancelAfterClientDone(*this, std::make_unique<CancelCancellationMode>());
}
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { TEST_P(CoreDeadlineTest, DeadlineAfterClientDone) {
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && CancelAfterClientDone(*this, std::make_unique<DeadlineCancellationMode>());
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) {
continue;
}
test_cancel_after_accept_and_writes_closed(config, cancellation_modes[i]);
}
} }
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 <memory>
#include <grpc/byte_buffer.h> #include "gmock/gmock.h"
#include <grpc/grpc.h> #include "gtest/gtest.h"
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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/gpr/useful.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
static std::unique_ptr<CoreTestFixture> begin_test(
const CoreTestConfiguration& config, const char* test_name, void CancelAfterInvoke6(CoreEnd2endTest& test,
cancellation_mode mode, size_t test_ops, grpc_channel_args* client_args, std::unique_ptr<CancellationMode> mode) {
grpc_channel_args* server_args) { auto c = test.NewClientCall("/service/method")
gpr_log(GPR_INFO, "Running test: %s/%s/%s [%" PRIdPTR " ops]", test_name, .Timeout(Duration::Seconds(5))
config.name, mode.name, test_ops); .Create();
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), CoreEnd2endTest::IncomingStatusOnClient server_status;
grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMessage server_message;
f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); c.NewBatch(1)
return f; .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 TEST_P(CoreDeadlineTest, DeadlineAfterInvoke4) {
static void test_cancel_after_invoke(const CoreTestConfiguration& config, CancelAfterInvoke4(*this, std::make_unique<DeadlineCancellationMode>());
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);
} }
void cancel_after_invoke(const CoreTestConfiguration& config) { TEST_P(CoreDeadlineTest, DeadlineAfterInvoke3) {
unsigned i, j; CancelAfterInvoke3(*this, std::make_unique<DeadlineCancellationMode>());
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);
}
}
} }
void cancel_after_invoke_pre_init(void) {} } // namespace grpc_core

@ -16,247 +16,83 @@
// //
// //
#include <string.h>
#include <functional>
#include <memory> #include <memory>
#include <grpc/byte_buffer.h> #include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.h"
#include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/end2end/tests/cancel_test_helpers.h" #include "test/core/end2end/tests/cancel_test_helpers.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name, namespace {
cancellation_mode mode, bool use_service_config,
grpc_channel_args* client_args, grpc_channel_args* server_args) { void CancelAfterRoundTrip(CoreEnd2endTest& test,
gpr_log(GPR_INFO, "Running test: %s/%s/%s/%s", test_name, config.name, std::unique_ptr<CancellationMode> mode,
mode.name, use_service_config ? "service_config" : "client_api"); Duration timeout) {
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), auto c = test.NewClientCall("/service/method").Timeout(timeout).Create();
grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMessage server_message;
f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); c.NewBatch(1)
return f; .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 TEST_P(CoreEnd2endTest, CancelAfterRoundTrip) {
static void test_cancel_after_round_trip(const CoreTestConfiguration& config, CancelAfterRoundTrip(*this, std::make_unique<CancelCancellationMode>(),
cancellation_mode mode, Duration::Seconds(5));
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);
}
} }
void cancel_after_round_trip(const CoreTestConfiguration& config) { TEST_P(CoreDeadlineTest, DeadlineAfterRoundTrip) {
unsigned i; CancelAfterRoundTrip(*this, std::make_unique<DeadlineCancellationMode>(),
Duration::Seconds(5));
}
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { TEST_P(CoreClientChannelTest, DeadlineAfterAcceptWithServiceConfig) {
if (config.feature_mask & FEATURE_MASK_DOES_NOT_SUPPORT_DEADLINES && InitServer(ChannelArgs());
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { InitClient(ChannelArgs().Set(
continue; GRPC_ARG_SERVICE_CONFIG,
} "{\n"
test_cancel_after_round_trip(config, cancellation_modes[i], " \"methodConfig\": [ {\n"
false /* use_service_config */); " \"name\": [\n"
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL && " { \"service\": \"service\", \"method\": \"method\" }\n"
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) { " ],\n"
test_cancel_after_round_trip(config, cancellation_modes[i], " \"timeout\": \"5s\"\n"
true /* use_service_config */); " } ]\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 "gtest/gtest.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 <grpc/status.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/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name, size_t num_ops,
grpc_channel_args* client_args, grpc_channel_args* server_args) { TEST_P(CoreEnd2endTest, CancelBeforeInvoke6) {
gpr_log(GPR_INFO, "Running test: %s/%s [%" PRIdPTR " ops]", test_name, auto c = NewClientCall("/service/method").Create();
config.name, num_ops); c.Cancel();
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), CoreEnd2endTest::IncomingStatusOnClient server_status;
grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMetadata server_initial_metadata;
f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); CoreEnd2endTest::IncomingMessage server_message;
f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); c.NewBatch(1)
return f; .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 TEST_P(CoreEnd2endTest, CancelBeforeInvoke5) {
static void test_cancel_before_invoke(const CoreTestConfiguration& config, auto c = NewClientCall("/service/method").Create();
size_t test_ops) { c.Cancel();
grpc_op ops[6]; CoreEnd2endTest::IncomingStatusOnClient server_status;
grpc_op* op; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_call* c; c.NewBatch(1)
auto f = .RecvStatusOnClient(server_status)
begin_test(config, "cancel_before_invoke", test_ops, nullptr, nullptr); .SendInitialMetadata({})
grpc_core::CqVerifier cqv(f->cq()); .SendMessage(RandomSlice(1024))
grpc_metadata_array initial_metadata_recv; .SendCloseFromClient()
grpc_metadata_array trailing_metadata_recv; .RecvInitialMetadata(server_initial_metadata);
grpc_metadata_array request_metadata_recv; Expect(1, AnyStatus());
grpc_call_details call_details; Step();
grpc_status_code status; EXPECT_EQ(server_status.status(), GRPC_STATUS_CANCELLED);
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);
grpc_metadata_array_destroy(&initial_metadata_recv); TEST_P(CoreEnd2endTest, CancelBeforeInvoke4) {
grpc_metadata_array_destroy(&trailing_metadata_recv); auto c = NewClientCall("/service/method").Create();
grpc_metadata_array_destroy(&request_metadata_recv); c.Cancel();
grpc_call_details_destroy(&call_details); 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); TEST_P(CoreEnd2endTest, CancelBeforeInvoke3) {
grpc_byte_buffer_destroy(response_payload_recv); auto c = NewClientCall("/service/method").Create();
grpc_slice_unref(details); 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) { TEST_P(CoreEnd2endTest, CancelBeforeInvoke1) {
size_t i; auto c = NewClientCall("/service/method").Create();
for (i = 1; i <= 6; i++) { c.Cancel();
test_cancel_before_invoke(config, i); 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 "gtest/gtest.h"
#include <memory>
#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/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 namespace grpc_core {
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);
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); TEST_P(CoreEnd2endTest, CancelInAVacuum) {
c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, NewClientCall("/service/method").Create().Cancel();
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);
} }
void cancel_in_a_vacuum(const CoreTestConfiguration& config) { TEST_P(CoreDeadlineTest, DeadlineInAVacuum) {
unsigned i; NewClientCall("/service/method").Create();
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_in_a_vacuum(config, cancellation_modes[i]);
}
} }
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 #ifndef GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H
#define 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> #include <grpc/status.h>
typedef struct { #include "test/core/end2end/end2end_tests.h"
const char* name;
grpc_call_error (*initiate_cancel)(grpc_call* call, void* reserved);
grpc_status_code expect_status;
const char* expect_details;
} cancellation_mode;
static grpc_call_error wait_for_deadline(grpc_call* /*call*/, void* reserved) { namespace grpc_core {
(void)reserved; class CancellationMode {
return GRPC_CALL_OK; 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[] = { class DeadlineCancellationMode : public CancellationMode {
{"cancel", grpc_call_cancel, GRPC_STATUS_CANCELLED, "CANCELLED"}, public:
{"deadline", wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED, void Apply(CoreEnd2endTest::Call&) override {}
"Deadline Exceeded"}, grpc_status_code ExpectedStatus() override {
return GRPC_STATUS_DEADLINE_EXCEEDED;
}
}; };
} // namespace grpc_core
#endif // GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H #endif // GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H

@ -16,122 +16,89 @@
// //
// //
#include <inttypes.h> #include "gtest/gtest.h"
#include <stdio.h>
#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/status.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/time.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/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); namespace grpc_core {
grpc_metadata_array_init(&trailing_metadata_recv); namespace {
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);
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"); char* dynamic_string = gpr_strdup("xyz");
grpc_call_cancel_with_status(c, GRPC_STATUS_UNIMPLEMENTED, dynamic_string, c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string);
nullptr);
// The API of \a description allows for it to be a dynamic/non-const // The API of \a description allows for it to be a dynamic/non-const
// string, test this guarantee. // string, test this guarantee.
gpr_free(dynamic_string); 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); TEST_P(CoreEnd2endTest, CancelWithStatus2) {
cqv.Verify(); auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
CoreEnd2endTest::IncomingMetadata server_initial_metadata;
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); CoreEnd2endTest::IncomingStatusOnClient server_status;
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); c.NewBatch(1)
.RecvStatusOnClient(server_status)
grpc_slice_unref(details); .RecvInitialMetadata(server_initial_metadata);
grpc_metadata_array_destroy(&initial_metadata_recv); char* dynamic_string = gpr_strdup("xyz");
grpc_metadata_array_destroy(&trailing_metadata_recv); c.CancelWithStatus(GRPC_STATUS_UNIMPLEMENTED, dynamic_string);
// The API of \a description allows for it to be a dynamic/non-const
grpc_call_unref(c); // 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, TEST_P(CoreEnd2endTest, CancelWithStatus3) {
size_t num_ops) { auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
auto f = begin_test(config, "test_invoke_simple_request", num_ops, nullptr, CoreEnd2endTest::IncomingMetadata server_initial_metadata;
nullptr); CoreEnd2endTest::IncomingStatusOnClient server_status;
simple_request_body(config, f.get(), num_ops); 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) { TEST_P(CoreEnd2endTest, CancelWithStatus4) {
size_t i; auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
for (i = 1; i <= 4; i++) { CoreEnd2endTest::IncomingMetadata server_initial_metadata;
test_invoke_simple_request(config, i); 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 "src/core/lib/channel/channelz.h"
#include <string.h>
#include <functional>
#include <memory>
#include <string> #include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.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/channel.h"
#include "src/core/lib/surface/server.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/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( using testing::HasSubstr;
const CoreTestConfiguration& config, const char* test_name, using testing::Not;
grpc_channel_args* client_args, grpc_channel_args* server_args) {
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); namespace grpc_core {
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args), namespace {
grpc_core::ChannelArgs::FromC(server_args));
f->InitServer(grpc_core::ChannelArgs::FromC(server_args)); void RunOneRequest(CoreEnd2endTest& test, bool request_is_success) {
f->InitClient(grpc_core::ChannelArgs::FromC(client_args)); auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
return f; 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*/, TEST_P(CoreEnd2endTest, Channelz) {
CoreTestFixture* f, bool request_is_success) { auto args = ChannelArgs()
grpc_call* c; .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 0)
grpc_call* s; .Set(GRPC_ARG_ENABLE_CHANNELZ, true);
grpc_core::CqVerifier cqv(f->cq()); InitServer(args);
grpc_op ops[6]; InitClient(args);
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);
error = grpc_server_request_call(f->server(), &s, &call_details, channelz::ChannelNode* channelz_channel =
&request_metadata_recv, f->cq(), f->cq(), grpc_channel_get_channelz_node(client());
grpc_core::CqVerifier::tag(101)); ASSERT_NE(channelz_channel, nullptr);
GPR_ASSERT(GRPC_CALL_OK == error);
cqv.Expect(grpc_core::CqVerifier::tag(101), true);
cqv.Verify();
memset(ops, 0, sizeof(ops)); channelz::ServerNode* channelz_server =
op = ops; Server::FromC(server())->channelz_node();
op->op = GRPC_OP_SEND_INITIAL_METADATA; ASSERT_NE(channelz_server, nullptr);
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);
std::string json = channelz_channel->RenderJsonString(); std::string json = channelz_channel->RenderJsonString();
// nothing is present yet // nothing is present yet
GPR_ASSERT(json.find("\"callsStarted\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"callsStarted\"")));
GPR_ASSERT(json.find("\"callsFailed\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"callsFailed\"")));
GPR_ASSERT(json.find("\"callsSucceeded\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"callsSucceeded\"")));
// one successful request // one successful request
run_one_request(config, f.get(), true); RunOneRequest(*this, true);
json = channelz_channel->RenderJsonString(); json = channelz_channel->RenderJsonString();
GPR_ASSERT(json.find("\"callsStarted\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"1\""));
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\""));
// one failed request // one failed request
run_one_request(config, f.get(), false); RunOneRequest(*this, false);
json = channelz_channel->RenderJsonString(); json = channelz_channel->RenderJsonString();
GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"2\""));
GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsFailed\":\"1\""));
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\""));
// channel tracing is not enabled, so these should not be preset. // channel tracing is not enabled, so these should not be preset.
GPR_ASSERT(json.find("\"trace\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"trace\"")));
GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"description\":\"Channel created\"")));
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"severity\":\"CT_INFO\"")));
json = channelz_server->RenderJsonString(); json = channelz_server->RenderJsonString();
GPR_ASSERT(json.find("\"callsStarted\":\"2\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsStarted\":\"2\""));
GPR_ASSERT(json.find("\"callsFailed\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsFailed\":\"1\""));
GPR_ASSERT(json.find("\"callsSucceeded\":\"1\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"callsSucceeded\":\"1\""));
// channel tracing is not enabled, so these should not be preset. // channel tracing is not enabled, so these should not be preset.
GPR_ASSERT(json.find("\"trace\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"trace\"")));
GPR_ASSERT(json.find("\"description\":\"Channel created\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"description\":\"Channel created\"")));
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") == json.npos); EXPECT_THAT(json, Not(HasSubstr("\"severity\":\"CT_INFO\"")));
json = channelz_server->RenderServerSockets(0, 100); 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( TEST_P(CoreEnd2endTest, ChannelzWithChannelTrace) {
const CoreTestConfiguration& config) { auto args =
grpc_arg arg[] = { ChannelArgs()
grpc_channel_arg_integer_create( .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024 * 1024)
const_cast<char*>(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), .Set(GRPC_ARG_ENABLE_CHANNELZ, true);
1024 * 1024), InitServer(args);
grpc_channel_arg_integer_create( InitClient(args);
const_cast<char*>(GRPC_ARG_ENABLE_CHANNELZ), true)};
grpc_channel_args args = {GPR_ARRAY_SIZE(arg), arg};
auto f = begin_test(config, "test_channelz_with_channel_trace", &args, &args); channelz::ChannelNode* channelz_channel =
grpc_core::channelz::ChannelNode* channelz_channel = grpc_channel_get_channelz_node(client());
grpc_channel_get_channelz_node(f->client()); ASSERT_NE(channelz_channel, nullptr);
GPR_ASSERT(channelz_channel != nullptr);
grpc_core::channelz::ServerNode* channelz_server = channelz::ServerNode* channelz_server =
grpc_core::Server::FromC(f->server())->channelz_node(); Server::FromC(server())->channelz_node();
GPR_ASSERT(channelz_server != nullptr); ASSERT_NE(channelz_server, nullptr);
run_one_request(config, f.get(), true); RunOneRequest(*this, true);
std::string json = channelz_channel->RenderJsonString(); std::string json = channelz_channel->RenderJsonString();
GPR_ASSERT(json.find("\"trace\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"trace\""));
GPR_ASSERT(json.find("\"description\":\"Channel created\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"description\":\"Channel created\""));
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"severity\":\"CT_INFO\""));
json = channelz_server->RenderJsonString(); json = channelz_server->RenderJsonString();
GPR_ASSERT(json.find("\"trace\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"trace\""));
GPR_ASSERT(json.find("\"description\":\"Server created\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"description\":\"Server created\""));
GPR_ASSERT(json.find("\"severity\":\"CT_INFO\"") != json.npos); EXPECT_THAT(json, HasSubstr("\"severity\":\"CT_INFO\""));
}
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);
} }
void channelz(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, ChannelzDisabled) {
test_channelz(config); auto args = ChannelArgs()
test_channelz_with_channel_trace(config); .Set(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 0)
test_channelz_disabled(config); .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/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 "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name, namespace {
grpc_channel_args* client_args, grpc_channel_args* server_args) {
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
auto f = config.create_fixture(grpc_core::ChannelArgs::FromC(client_args),
grpc_core::ChannelArgs::FromC(server_args));
f->InitServer(grpc_core::ChannelArgs::FromC(server_args));
f->InitClient(grpc_core::ChannelArgs::FromC(client_args));
return f;
}
// Client streaming test where the client sends a bunch of messages and the // 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. // 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 // Client writes fail after that due to the end of stream and the client
// subsequently requests and receives the status. // subsequently requests and receives the status.
static void test_client_streaming(const CoreTestConfiguration& config, void ClientStreaming(CoreEnd2endTest& test, int messages) {
int messages) { auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
auto f = begin_test(config, "test_client_streaming", nullptr, nullptr);
grpc_call* c; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_call* s; c.NewBatch(1).SendInitialMetadata({}).RecvInitialMetadata(
grpc_core::CqVerifier cqv(f->cq()); server_initial_metadata);
grpc_op ops[6]; auto s = test.RequestCall(100);
grpc_op* op; test.Expect(100, true);
grpc_metadata_array initial_metadata_recv; test.Step();
grpc_metadata_array trailing_metadata_recv; s.NewBatch(101).SendInitialMetadata({});
grpc_metadata_array request_metadata_recv; test.Expect(101, true);
grpc_call_details call_details; test.Expect(1, true);
grpc_status_code status; test.Step();
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();
// Client writes bunch of messages and server reads them // Client writes bunch of messages and server reads them
for (i = 0; i < messages; i++) { for (int i = 0; i < messages; i++) {
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); c.NewBatch(2).SendMessage("hello world");
memset(ops, 0, sizeof(ops)); CoreEnd2endTest::IncomingMessage client_message;
op = ops; s.NewBatch(102).RecvMessage(client_message);
op->op = GRPC_OP_SEND_MESSAGE; test.Expect(2, true);
op->data.send_message.send_message = request_payload; test.Expect(102, true);
op->flags = 0; test.Step();
op->reserved = nullptr; EXPECT_EQ(client_message.payload(), "hello world");
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);
} }
// Server sends status denoting end of stream // Server sends status denoting end of stream
memset(ops, 0, sizeof(ops)); s.NewBatch(103).SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {});
op = ops; test.Expect(103, true);
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; test.Step();
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();
// Do an empty verify to make sure that the client receives the status // 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 // Client tries sending another message which should fail
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); c.NewBatch(3).SendMessage("hello world");
memset(ops, 0, sizeof(ops)); test.Expect(3, false);
op = ops; test.Step();
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();
// Client sends close and requests status // Client sends close and requests status
memset(ops, 0, sizeof(ops)); CoreEnd2endTest::IncomingStatusOnClient server_status;
op = ops; c.NewBatch(4).SendCloseFromClient().RecvStatusOnClient(server_status);
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; test.Expect(4, true);
op->flags = 0; test.Step();
op->reserved = nullptr; EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
op++; EXPECT_EQ(server_status.message(), "xyz");
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);
} }
void client_streaming(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, ClientStreaming0) { ClientStreaming(*this, 0); }
for (int i = 0; i < 10; i++) { TEST_P(CoreEnd2endTest, ClientStreaming1) { ClientStreaming(*this, 1); }
test_client_streaming(config, i); 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 <stdint.h>
#include <string.h>
#include <functional>
#include <initializer_list> #include <initializer_list>
#include <memory>
#include <string> #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/compression.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/impl/propagation_bits.h>
#include <grpc/slice.h>
#include <grpc/status.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.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/bitset.h" #include "src/core/lib/gprpp/bitset.h"
#include "src/core/lib/surface/call.h" #include "src/core/lib/gprpp/time.h"
#include "src/core/lib/surface/call_test_only.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.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( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name, namespace {
uint32_t send_flags_bitmask,
grpc_compression_algorithm algorithm_to_disable, class TestConfigurator {
grpc_compression_algorithm requested_client_compression_algorithm, public:
grpc_status_code expected_error, grpc_metadata* client_metadata, explicit TestConfigurator(CoreEnd2endTest& test) : test_(test) {}
bool decompress_in_core) {
grpc_call* c; TestConfigurator& DisableAlgorithmAtServer(
grpc_call* s; grpc_compression_algorithm algorithm) {
grpc_slice request_payload_slice; server_args_ =
grpc_byte_buffer* request_payload; server_args_.Set(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
grpc_core::ChannelArgs client_args; BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT>()
grpc_core::ChannelArgs server_args; .SetAll(true)
.Set(algorithm, false)
grpc_op ops[6]; .ToInt<uint32_t>());
grpc_op* op; return *this;
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);
} }
auto f = begin_test(config, test_name, client_args.ToC().get(), TestConfigurator& ClientDefaultAlgorithm(
server_args.ToC().get(), decompress_in_core); grpc_compression_algorithm algorithm) {
grpc_core::CqVerifier cqv(f->cq()); client_args_ =
client_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); return *this;
c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, }
f->cq(), grpc_slice_from_static_string("/foo"),
nullptr, deadline, nullptr); TestConfigurator& ServerDefaultAlgorithm(
GPR_ASSERT(c); grpc_compression_algorithm algorithm) {
server_args_ =
grpc_metadata_array_init(&initial_metadata_recv); server_args_.Set(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
grpc_metadata_array_init(&trailing_metadata_recv); return *this;
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;
} }
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( TestConfigurator& DecompressInApp() {
const CoreTestConfiguration& config, const char* test_name, client_args_ =
uint32_t client_send_flags_bitmask, client_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false);
grpc_compression_algorithm default_client_channel_compression_algorithm, server_args_ =
grpc_compression_algorithm default_server_channel_compression_algorithm, server_args_.Set(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION, false);
grpc_compression_algorithm expected_algorithm_from_client, return *this;
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);
} }
auto f = begin_test(config, test_name, client_args.ToC().get(),
server_args.ToC().get(), decompress_in_core); TestConfigurator& ExpectedAlgorithmFromClient(
grpc_core::CqVerifier cqv(f->cq()); grpc_compression_algorithm algorithm) {
expected_algorithm_from_client_ = algorithm;
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); return *this;
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);
} }
memset(ops, 0, sizeof(ops));
op = ops; TestConfigurator& ExpectedAlgorithmFromServer(
op->op = GRPC_OP_SEND_INITIAL_METADATA; grpc_compression_algorithm algorithm) {
if (client_init_metadata != nullptr) { expected_algorithm_from_server_ = algorithm;
op->data.send_initial_metadata.count = 1; return *this;
op->data.send_initial_metadata.metadata = client_init_metadata;
} else {
op->data.send_initial_metadata.count = 0;
} }
op->flags = 0;
op->reserved = nullptr; void DisabledAlgorithmTest() {
op++; Init();
op->op = GRPC_OP_RECV_INITIAL_METADATA; auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; auto s = test_.RequestCall(101);
op->flags = 0; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
op->reserved = nullptr; CoreEnd2endTest::IncomingStatusOnClient server_status;
op++; c.NewBatch(1)
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; .SendInitialMetadata({})
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; .SendMessage(std::string(1024, 'x'))
op->data.recv_status_on_client.status = &status; .SendCloseFromClient()
op->data.recv_status_on_client.status_details = &details; .RecvInitialMetadata(server_initial_metadata)
op->flags = 0; .RecvStatusOnClient(server_status);
op->reserved = nullptr; test_.Expect(101, true);
op++; test_.Expect(1, true);
error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), test_.Step();
grpc_core::CqVerifier::tag(1), nullptr); CoreEnd2endTest::IncomingMessage client_message;
GPR_ASSERT(GRPC_CALL_OK == error); s.NewBatch(102).SendInitialMetadata({}).RecvMessage(client_message);
CoreEnd2endTest::IncomingCloseOnServer client_close;
error = grpc_server_request_call(f->server(), &s, &call_details, test_.Expect(102, false);
&request_metadata_recv, f->cq(), f->cq(), s.NewBatch(103).RecvCloseOnServer(client_close);
grpc_core::CqVerifier::tag(100)); test_.Expect(103, true);
GPR_ASSERT(GRPC_CALL_OK == error); test_.Step();
cqv.Expect(grpc_core::CqVerifier::tag(100), true); // call was cancelled (closed) ...
cqv.Verify(); EXPECT_NE(client_close.was_cancelled(), 0);
// with a certain error
GPR_ASSERT(grpc_core::BitCount( EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
grpc_call_test_only_get_encodings_accepted_by_peer(s)) == // and we expect a specific reason for it
GRPC_COMPRESS_ALGORITHMS_COUNT); EXPECT_EQ(server_status.message(),
GPR_ASSERT( "Compression algorithm 'gzip' is disabled.");
grpc_core::GetBit(grpc_call_test_only_get_encodings_accepted_by_peer(s), EXPECT_EQ(s.method(), "/foo");
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;
} }
op->flags = 0;
op->reserved = nullptr; void RequestWithPayload(
op++; uint32_t client_send_flags_bitmask,
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; std::initializer_list<std::pair<absl::string_view, absl::string_view>>
op->data.recv_close_on_server.cancelled = &was_cancelled; client_init_metadata) {
op->flags = 0; Init();
op->reserved = nullptr; auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
op++; CoreEnd2endTest::IncomingStatusOnClient server_status;
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_core::CqVerifier::tag(101), nullptr); c.NewBatch(1)
GPR_ASSERT(GRPC_CALL_OK == error); .SendInitialMetadata(client_init_metadata)
for (int i = 0; i < 2; i++) { .RecvInitialMetadata(server_initial_metadata)
response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); .RecvStatusOnClient(server_status);
auto s = test_.RequestCall(100);
if (i > 0 || !send_message_before_initial_metadata) { test_.Expect(100, true);
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); test_.Step();
memset(ops, 0, sizeof(ops)); EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all());
op = ops; CoreEnd2endTest::IncomingCloseOnServer client_close;
op->op = GRPC_OP_SEND_MESSAGE; s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close);
op->data.send_message.send_message = request_payload; for (int i = 0; i < 2; i++) {
op->flags = client_send_flags_bitmask; c.NewBatch(2).SendMessage(std::string(1024, 'x'),
op->reserved = nullptr; client_send_flags_bitmask);
op++; test_.Expect(2, true);
error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), CoreEnd2endTest::IncomingMessage client_message;
grpc_core::CqVerifier::tag(2), nullptr); s.NewBatch(102).RecvMessage(client_message);
GPR_ASSERT(GRPC_CALL_OK == error); test_.Expect(102, true);
cqv.Expect(grpc_core::CqVerifier::tag(2), 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)); void RequestWithSendMessageBeforeInitialMetadata() {
op = ops; Init();
op->op = GRPC_OP_RECV_MESSAGE; auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
op->data.recv_message.recv_message = &request_payload_recv; c.NewBatch(2).SendMessage(std::string(1024, 'x'));
op->flags = 0; test_.Expect(2, true);
op->reserved = nullptr; CoreEnd2endTest::IncomingStatusOnClient server_status;
op++; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), c.NewBatch(1)
grpc_core::CqVerifier::tag(102), nullptr); .SendInitialMetadata({})
GPR_ASSERT(GRPC_CALL_OK == error); .RecvInitialMetadata(server_initial_metadata)
.RecvStatusOnClient(server_status);
cqv.Expect(grpc_core::CqVerifier::tag(102), true); auto s = test_.RequestCall(100);
cqv.Verify(); test_.Expect(100, true);
test_.Step();
GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); EXPECT_TRUE(s.GetEncodingsAcceptedByPeer().all());
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); CoreEnd2endTest::IncomingCloseOnServer client_close;
GPR_ASSERT(request_payload_recv->data.raw.compression == s.NewBatch(101).SendInitialMetadata({}).RecvCloseOnServer(client_close);
(decompress_in_core ? GRPC_COMPRESS_NONE for (int i = 0; i < 2; i++) {
: expected_algorithm_from_client)); if (i > 0) {
c.NewBatch(2).SendMessage(std::string(1024, 'x'));
memset(ops, 0, sizeof(ops)); test_.Expect(2, true);
op = ops; }
op->op = GRPC_OP_SEND_MESSAGE; CoreEnd2endTest::IncomingMessage client_message;
op->data.send_message.send_message = response_payload; s.NewBatch(102).RecvMessage(client_message);
op->flags = 0; test_.Expect(102, true);
op->reserved = nullptr; test_.Step();
op++; EXPECT_EQ(client_message.byte_buffer_type(), GRPC_BB_RAW);
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), EXPECT_EQ(client_message.payload(), std::string(1024, 'x'));
grpc_core::CqVerifier::tag(103), nullptr); EXPECT_EQ(client_message.compression(), expected_algorithm_from_client_);
GPR_ASSERT(GRPC_CALL_OK == error); s.NewBatch(103).SendMessage(std::string(1024, 'y'));
CoreEnd2endTest::IncomingMessage server_message;
memset(ops, 0, sizeof(ops)); c.NewBatch(3).RecvMessage(server_message);
op = ops; test_.Expect(103, true);
op->op = GRPC_OP_RECV_MESSAGE; test_.Expect(3, true);
op->data.recv_message.recv_message = &response_payload_recv; test_.Step();
op->flags = 0; EXPECT_EQ(server_message.byte_buffer_type(), GRPC_BB_RAW);
op->reserved = nullptr; EXPECT_EQ(server_message.payload(), std::string(1024, 'y'));
op++; EXPECT_EQ(server_message.compression(), expected_algorithm_from_server_);
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));
} }
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); void RequestWithServerLevel(grpc_compression_level server_compression_level) {
grpc_byte_buffer_destroy(response_payload); Init();
grpc_byte_buffer_destroy(request_payload_recv); auto c = test_.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
grpc_byte_buffer_destroy(response_payload_recv); 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); private:
void Init() {
memset(ops, 0, sizeof(ops)); test_.InitClient(client_args_);
op = ops; test_.InitServer(server_args_);
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; }
op->flags = 0;
op->reserved = nullptr; CoreEnd2endTest& test_;
op++; ChannelArgs client_args_ = ChannelArgs().Set(
error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE);
grpc_core::CqVerifier::tag(4), nullptr); ChannelArgs server_args_ = ChannelArgs().Set(
GPR_ASSERT(GRPC_CALL_OK == error); GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, GRPC_COMPRESS_NONE);
grpc_compression_algorithm expected_algorithm_from_client_ =
memset(ops, 0, sizeof(ops)); GRPC_COMPRESS_NONE;
op = ops; grpc_compression_algorithm expected_algorithm_from_server_ =
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; GRPC_COMPRESS_NONE;
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"); TEST_P(Http2SingleHopTest, DisabledAlgorithmDecompressInCore) {
op->data.send_status_from_server.status_details = &status_details; TestConfigurator(*this)
op->flags = 0; .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
op->reserved = nullptr; .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP)
op++; .DisabledAlgorithmTest();
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); TEST_P(Http2SingleHopTest, DisabledAlgorithmDecompressInApp) {
TestConfigurator(*this)
cqv.Expect(grpc_core::CqVerifier::tag(1), true); .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
cqv.Expect(grpc_core::CqVerifier::tag(4), true); .DisableAlgorithmAtServer(GRPC_COMPRESS_GZIP)
cqv.Expect(grpc_core::CqVerifier::tag(101), true); .DecompressInApp()
cqv.Expect(grpc_core::CqVerifier::tag(104), true); .DisabledAlgorithmTest();
cqv.Verify(); }
GPR_ASSERT(status == GRPC_STATUS_OK); TEST_P(Http2SingleHopTest,
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); RequestWithExceptionallyUncompressedPayloadDecompressInCore) {
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); TestConfigurator(*this)
GPR_ASSERT(was_cancelled == 0); .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
.ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
grpc_slice_unref(details); .RequestWithPayload(GRPC_WRITE_NO_COMPRESS, {});
grpc_metadata_array_destroy(&initial_metadata_recv); }
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv); TEST_P(Http2SingleHopTest,
grpc_call_details_destroy(&call_details); RequestWithExceptionallyUncompressedPayloadDecompressInApp) {
TestConfigurator(*this)
grpc_call_unref(c); .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
grpc_call_unref(s); .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( TEST_P(Http2SingleHopTest,
const CoreTestConfiguration& config, const char* test_name, RequestWithSendMessageBeforeInitialMetadataDecompressInApp) {
uint32_t client_send_flags_bitmask, TestConfigurator(*this)
grpc_compression_algorithm default_client_channel_compression_algorithm, .ClientDefaultAlgorithm(GRPC_COMPRESS_GZIP)
grpc_compression_algorithm default_server_channel_compression_algorithm, .ServerDefaultAlgorithm(GRPC_COMPRESS_GZIP)
grpc_compression_algorithm expected_algorithm_from_client, .DecompressInApp()
grpc_compression_algorithm expected_algorithm_from_server, .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
grpc_metadata* client_init_metadata, bool set_server_level, .ExpectedAlgorithmFromServer(GRPC_COMPRESS_GZIP)
grpc_compression_level server_compression_level, .RequestWithSendMessageBeforeInitialMetadata();
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);
} }
static void test_invoke_request_with_exceptionally_uncompressed_payload( TEST_P(Http2SingleHopTest, RequestWithServerLevelDecompressInCore) {
const CoreTestConfiguration& config) { TestConfigurator(*this).RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH);
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);
} }
static void test_invoke_request_with_uncompressed_payload( TEST_P(Http2SingleHopTest, RequestWithServerLevelDecompressInApp) {
const CoreTestConfiguration& config) { TestConfigurator(*this)
request_with_payload_template( .DecompressInApp()
config, "test_invoke_request_with_uncompressed_payload", 0, .ExpectedAlgorithmFromServer(GRPC_COMPRESS_DEFLATE)
GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, .RequestWithServerLevel(GRPC_COMPRESS_LEVEL_HIGH);
GRPC_COMPRESS_NONE, nullptr, false,
/* ignored */ GRPC_COMPRESS_LEVEL_NONE, false);
} }
static void test_invoke_request_with_compressed_payload( TEST_P(Http2SingleHopTest,
const CoreTestConfiguration& config) { RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInCore) {
request_with_payload_template( TestConfigurator(*this).RequestWithPayload(
config, "test_invoke_request_with_compressed_payload", 0, 0, {{"grpc-internal-encoding-request", "gzip"}});
GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_GZIP, nullptr, false,
/* ignored */ GRPC_COMPRESS_LEVEL_NONE, false);
} }
static void test_invoke_request_with_send_message_before_initial_metadata( TEST_P(Http2SingleHopTest,
const CoreTestConfiguration& config) { RequestWithCompressedPayloadMetadataOverrideNoneToGzipDecompressInApp) {
request_with_payload_template( TestConfigurator(*this)
config, "test_invoke_request_with_compressed_payload", 0, .DecompressInApp()
GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
GRPC_COMPRESS_GZIP, nullptr, false, .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}});
/* ignored */ GRPC_COMPRESS_LEVEL_NONE, true);
} }
static void test_invoke_request_with_server_level( TEST_P(
const CoreTestConfiguration& config) { Http2SingleHopTest,
request_with_payload_template( RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInCore) {
config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE, TestConfigurator(*this)
GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */, .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
nullptr, true, GRPC_COMPRESS_LEVEL_HIGH, false); .RequestWithPayload(0, {{"grpc-internal-encoding-request", "gzip"}});
} }
static void test_invoke_request_with_compressed_payload_md_override( TEST_P(
const CoreTestConfiguration& config) { Http2SingleHopTest,
grpc_metadata gzip_compression_override; RequestWithCompressedPayloadMetadataOverrideDeflateToGzipDecompressInApp) {
grpc_metadata identity_compression_override; TestConfigurator(*this)
.ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
gzip_compression_override.key = .DecompressInApp()
grpc_slice_from_static_string("grpc-internal-encoding-request"); .ExpectedAlgorithmFromClient(GRPC_COMPRESS_GZIP)
gzip_compression_override.value = grpc_slice_from_static_string("gzip"); .RequestWithPayload(0, {{"grpc-internal-encoding-request", "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);
} }
static void test_invoke_request_with_disabled_algorithm( TEST_P(
const CoreTestConfiguration& config) { Http2SingleHopTest,
request_for_disabled_algorithm(config, RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInCore) {
"test_invoke_request_with_disabled_algorithm", TestConfigurator(*this)
0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
GRPC_STATUS_UNIMPLEMENTED, nullptr, false); .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}});
request_for_disabled_algorithm(config,
"test_invoke_request_with_disabled_algorithm",
0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
GRPC_STATUS_UNIMPLEMENTED, nullptr, true);
} }
void compressed_payload(const CoreTestConfiguration& config) { TEST_P(
test_invoke_request_with_exceptionally_uncompressed_payload(config); Http2SingleHopTest,
test_invoke_request_with_uncompressed_payload(config); RequestWithCompressedPayloadMetadataOverrideDeflateToIdentityDecompressInApp) {
test_invoke_request_with_compressed_payload(config); TestConfigurator(*this)
test_invoke_request_with_send_message_before_initial_metadata(config); .ClientDefaultAlgorithm(GRPC_COMPRESS_DEFLATE)
test_invoke_request_with_server_level(config); .DecompressInApp()
test_invoke_request_with_compressed_payload_md_override(config); .RequestWithPayload(0, {{"grpc-internal-encoding-request", "identity"}});
test_invoke_request_with_disabled_algorithm(config);
} }
void compressed_payload_pre_init(void) {} } // namespace
} // namespace grpc_core

@ -16,213 +16,73 @@
// //
// //
#include <functional> #include "gmock/gmock.h"
#include <memory> #include "gtest/gtest.h"
#include <grpc/grpc.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/channel/channel_args.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/gprpp/time.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/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
typedef struct { namespace grpc_core {
gpr_event started; namespace {
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));
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 // channels should start life in IDLE, and stay there
GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 0) == EXPECT_EQ(CheckConnectivityState(false), GRPC_CHANNEL_IDLE);
GRPC_CHANNEL_IDLE); Step(Duration::Milliseconds(100));
gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); EXPECT_EQ(CheckConnectivityState(false), GRPC_CHANNEL_IDLE);
GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 0) ==
GRPC_CHANNEL_IDLE);
// start watching for a change // start watching for a change
gpr_log(GPR_DEBUG, "watching"); WatchConnectivityState(GRPC_CHANNEL_IDLE, Duration::Milliseconds(500), 1);
grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_IDLE, Expect(1, false);
gpr_now(GPR_CLOCK_MONOTONIC), f->cq(), Step(Duration::Minutes(1));
grpc_core::CqVerifier::tag(1));
// eventually the child thread completion should trigger
thd.Join();
// check that we're still in idle, and start connecting // check that we're still in idle, and start connecting
GPR_ASSERT(grpc_channel_check_connectivity_state(f->client(), 1) == EXPECT_EQ(CheckConnectivityState(true), GRPC_CHANNEL_IDLE);
GRPC_CHANNEL_IDLE);
// start watching for a change // start watching for a change
grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_IDLE, WatchConnectivityState(GRPC_CHANNEL_IDLE, Duration::Seconds(10), 2);
grpc_timeout_seconds_to_deadline(10),
f->cq(), grpc_core::CqVerifier::tag(2));
// and now the watch should trigger // and now the watch should trigger
cqv.Expect(grpc_core::CqVerifier::tag(2), true); Expect(2, true);
cqv.Verify(); Step();
state = grpc_channel_check_connectivity_state(f->client(), 0); grpc_connectivity_state state = CheckConnectivityState(false);
GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || EXPECT_THAT(state, ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE,
state == GRPC_CHANNEL_CONNECTING); GRPC_CHANNEL_CONNECTING));
// quickly followed by a transition to TRANSIENT_FAILURE // quickly followed by a transition to TRANSIENT_FAILURE
grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_CONNECTING, WatchConnectivityState(GRPC_CHANNEL_CONNECTING, Duration::Seconds(10), 3);
grpc_timeout_seconds_to_deadline(10), Expect(3, true);
f->cq(), grpc_core::CqVerifier::tag(3)); Step();
cqv.Expect(grpc_core::CqVerifier::tag(3), true); state = CheckConnectivityState(false);
cqv.Verify(); EXPECT_THAT(state, ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE,
state = grpc_channel_check_connectivity_state(f->client(), 0); GRPC_CHANNEL_CONNECTING));
GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
state == GRPC_CHANNEL_CONNECTING);
gpr_log(GPR_DEBUG, "*** STARTING SERVER ***");
// now let's bring up a server to connect to // now let's bring up a server to connect to
f->InitServer(grpc_core::ChannelArgs()); InitServer(ChannelArgs());
gpr_log(GPR_DEBUG, "*** STARTED SERVER ***");
// we'll go through some set of transitions (some might be missed), until // we'll go through some set of transitions (some might be missed), until
// READY is reached // READY is reached
while (state != GRPC_CHANNEL_READY) { while (state != GRPC_CHANNEL_READY) {
grpc_channel_watch_connectivity_state( WatchConnectivityState(state, Duration::Seconds(10), 4);
f->client(), state, grpc_timeout_seconds_to_deadline(10), f->cq(), Expect(4, true);
grpc_core::CqVerifier::tag(4)); Step(Duration::Seconds(20));
cqv.Expect(grpc_core::CqVerifier::tag(4), true); state = CheckConnectivityState(false);
cqv.Verify(grpc_core::Duration::Seconds(20)); EXPECT_THAT(state,
state = grpc_channel_check_connectivity_state(f->client(), 0); ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE,
GPR_ASSERT(state == GRPC_CHANNEL_READY || GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_READY));
state == GRPC_CHANNEL_CONNECTING ||
state == GRPC_CHANNEL_TRANSIENT_FAILURE);
} }
// bring down the server again // bring down the server again
// we should go immediately to TRANSIENT_FAILURE // we should go immediately to TRANSIENT_FAILURE
gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); WatchConnectivityState(GRPC_CHANNEL_READY, Duration::Seconds(10), 5);
ShutdownServerAndNotify(1000);
grpc_channel_watch_connectivity_state(f->client(), GRPC_CHANNEL_READY, Expect(5, true);
grpc_timeout_seconds_to_deadline(10), Expect(1000, true);
f->cq(), grpc_core::CqVerifier::tag(5)); Step();
state = CheckConnectivityState(false);
grpc_server_shutdown_and_notify(f->server(), f->cq(), EXPECT_THAT(state,
grpc_core::CqVerifier::tag(0xdead)); ::testing::AnyOf(GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_CHANNEL_CONNECTING, GRPC_CHANNEL_IDLE));
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);
} }
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/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/time.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.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); using testing::AnyOf;
GPR_ASSERT(peer != nullptr); using testing::StartsWith;
gpr_log(GPR_DEBUG, "server_peer=%s", peer);
gpr_free(peer); namespace grpc_core {
peer = grpc_call_get_peer(c); namespace {
GPR_ASSERT(peer != nullptr);
gpr_log(GPR_DEBUG, "client_peer=%s", peer); TEST_P(CoreClientChannelTest, DefaultHost) {
gpr_free(peer); auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
EXPECT_NE(c.GetPeer(), absl::nullopt);
memset(ops, 0, sizeof(ops)); IncomingStatusOnClient server_status;
op = ops; IncomingMetadata server_initial_metadata;
op->op = GRPC_OP_SEND_INITIAL_METADATA; c.NewBatch(1)
op->data.send_initial_metadata.count = 0; .SendInitialMetadata({})
op->flags = 0; .SendCloseFromClient()
op->reserved = nullptr; .RecvInitialMetadata(server_initial_metadata)
op++; .RecvStatusOnClient(server_status);
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; auto s = RequestCall(101);
op->data.send_status_from_server.trailing_metadata_count = 0; Expect(101, true);
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; Step();
grpc_slice status_details = grpc_slice_from_static_string("xyz"); EXPECT_NE(s.GetPeer(), absl::nullopt);
op->data.send_status_from_server.status_details = &status_details; EXPECT_NE(c.GetPeer(), absl::nullopt);
op->flags = 0; IncomingCloseOnServer client_close;
op->reserved = nullptr; s.NewBatch(102)
op++; .SendInitialMetadata({})
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
op->data.recv_close_on_server.cancelled = &was_cancelled; .RecvCloseOnServer(client_close);
op->flags = 0; Expect(102, true);
op->reserved = nullptr; Expect(1, true);
op++; Step();
error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
grpc_core::CqVerifier::tag(102), nullptr); EXPECT_EQ(server_status.message(), "xyz");
GPR_ASSERT(error == GRPC_CALL_OK); EXPECT_EQ(s.method(), "/foo");
if (GetParam()->overridden_call_host != nullptr) {
cqv.Expect(grpc_core::CqVerifier::tag(102), true); EXPECT_EQ(GetParam()->overridden_call_host, s.host());
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);
} else { } else {
GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9) || EXPECT_THAT(s.host(), AnyOf(StartsWith("localhost"),
grpc_slice_buf_start_eq(call_details.host, "127.0.0.1", 9)); StartsWith("127.0.0.1"), StartsWith("[::1]")));
} }
GPR_ASSERT(was_cancelled == 0); EXPECT_FALSE(client_close.was_cancelled());
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);
} }
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/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.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/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, #ifndef GPR_WINDOWS // b/148110727 for more details
&request_metadata_recv, f->cq(), f->cq(), namespace grpc_core {
grpc_core::CqVerifier::tag(101));
GPR_ASSERT(GRPC_CALL_OK == error); static void OneRequestAndShutdownServer(CoreEnd2endTest& test) {
cqv.Expect(grpc_core::CqVerifier::tag(101), true); auto c = test.NewClientCall("/service/method")
cqv.Verify(); .Timeout(Duration::Seconds(5))
.Create();
// should be able to shut down the server early CoreEnd2endTest::IncomingMetadata server_initial_md;
// - and still complete the request CoreEnd2endTest::IncomingStatusOnClient server_status;
grpc_server_shutdown_and_notify(f->server(), f->cq(), c.NewBatch(1)
grpc_core::CqVerifier::tag(1000)); .SendInitialMetadata({})
.SendCloseFromClient()
memset(ops, 0, sizeof(ops)); .RecvInitialMetadata(server_initial_md)
op = ops; .RecvStatusOnClient(server_status);
op->op = GRPC_OP_SEND_INITIAL_METADATA; auto s = test.RequestCall(101);
op->data.send_initial_metadata.count = 0; test.Expect(101, true);
op->flags = 0; test.Step();
op->reserved = nullptr; test.ShutdownServerAndNotify(1000);
op++; CoreEnd2endTest::IncomingCloseOnServer client_closed;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; s.NewBatch(102)
op->data.send_status_from_server.trailing_metadata_count = 0; .SendInitialMetadata({})
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
grpc_slice status_details = grpc_slice_from_static_string("xyz"); .RecvCloseOnServer(client_closed);
op->data.send_status_from_server.status_details = &status_details; test.Expect(102, true);
op->flags = 0; test.Expect(1, true);
op->reserved = nullptr; test.Expect(1000, true);
op++; test.Step();
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();
// Please refer https://github.com/grpc/grpc/issues/21221 for additional // Please refer https://github.com/grpc/grpc/issues/21221 for additional
// details. // details.
// TODO(yashykt@) - The following line should be removeable after C-Core // 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 // test remains flaky even after this, an alternative fix would be to send a
// request when the server is in the shut down state. // request when the server is in the shut down state.
// //
cqv.VerifyEmpty(); test.Step();
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
GPR_ASSERT(was_cancelled == 0);
grpc_slice_unref(details); EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
grpc_metadata_array_destroy(&initial_metadata_recv); EXPECT_EQ(server_status.message(), "xyz");
grpc_metadata_array_destroy(&trailing_metadata_recv); EXPECT_EQ(s.method(), "/service/method");
grpc_metadata_array_destroy(&request_metadata_recv); EXPECT_FALSE(client_closed.was_cancelled());
grpc_call_details_destroy(&call_details);
grpc_call_unref(c);
grpc_call_unref(s);
} }
static void disappearing_server_test(const CoreTestConfiguration& config) { TEST_P(CoreClientChannelTest, DisappearingServer) {
auto f = OneRequestAndShutdownServer(*this);
config.create_fixture(grpc_core::ChannelArgs(), grpc_core::ChannelArgs()); InitServer(ChannelArgs());
grpc_core::CqVerifier cqv(f->cq()); OneRequestAndShutdownServer(*this);
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);
} }
void disappearing_server(const CoreTestConfiguration& config) { } // namespace grpc_core
GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION);
#ifndef GPR_WINDOWS // b/148110727 for more details
disappearing_server_test(config);
#endif // GPR_WINDOWS #endif // GPR_WINDOWS
}
void disappearing_server_pre_init(void) {}

@ -16,60 +16,17 @@
// //
// //
#include <functional> #include "gtest/gtest.h"
#include <memory>
#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/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 = namespace grpc_core {
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());
}
void empty_batch(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, EmptyBatch) {
test_invoke_empty_body(config); 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 <stdint.h>
#include <string.h>
#include <functional>
#include <memory>
#include "absl/status/status.h" #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/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_fwd.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/status_helper.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/closure.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/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. namespace grpc_core {
static void test_request(const CoreTestConfiguration& config) { namespace {
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);
}
//****************************************************************************** //******************************************************************************
// Test filter - always closes incoming requests // Test filter - always closes incoming requests
@ -161,19 +51,19 @@ typedef struct {
uint8_t unused; uint8_t unused;
} channel_data; } 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); grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
grpc_core::Closure::Run( Closure::Run(
DEBUG_LOCATION, calld->recv_im_ready, DEBUG_LOCATION, calld->recv_im_ready,
grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING( grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING(
"Failure that's not preventable.", &error, 1), "Failure that's not preventable.", &error, 1),
grpc_core::StatusIntProperty::kRpcStatus, StatusIntProperty::kRpcStatus,
GRPC_STATUS_PERMISSION_DENIED)); GRPC_STATUS_PERMISSION_DENIED));
} }
static void start_transport_stream_op_batch( void start_transport_stream_op_batch(grpc_call_element* elem,
grpc_call_element* elem, grpc_transport_stream_op_batch* op) { grpc_transport_stream_op_batch* op) {
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
if (op->recv_initial_metadata) { if (op->recv_initial_metadata) {
calld->recv_im_ready = calld->recv_im_ready =
@ -184,23 +74,23 @@ static void start_transport_stream_op_batch(
grpc_call_next_op(elem, op); grpc_call_next_op(elem, op);
} }
static grpc_error_handle init_call_elem( grpc_error_handle init_call_elem(grpc_call_element* /*elem*/,
grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { const grpc_call_element_args* /*args*/) {
return absl::OkStatus(); return absl::OkStatus();
} }
static void destroy_call_elem(grpc_call_element* /*elem*/, void destroy_call_elem(grpc_call_element* /*elem*/,
const grpc_call_final_info* /*final_info*/, const grpc_call_final_info* /*final_info*/,
grpc_closure* /*ignored*/) {} grpc_closure* /*ignored*/) {}
static grpc_error_handle init_channel_elem( grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/,
grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { grpc_channel_element_args* /*args*/) {
return absl::OkStatus(); 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, start_transport_stream_op_batch,
nullptr, nullptr,
grpc_channel_next_op, grpc_channel_next_op,
@ -215,22 +105,29 @@ static const grpc_channel_filter test_filter = {
grpc_channel_next_get_info, grpc_channel_next_get_info,
"filter_causes_close"}; "filter_causes_close"};
//****************************************************************************** TEST_P(CoreEnd2endTest, FilterCausesClose) {
// Registration CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
// builder->channel_init()->RegisterStage(
GRPC_SERVER_CHANNEL, 0, [](ChannelStackBuilder* builder) {
void filter_causes_close(const CoreTestConfiguration& config) { builder->PrependFilter(&test_filter);
grpc_core::CoreConfiguration::RunWithSpecialConfiguration( return true;
[](grpc_core::CoreConfiguration::Builder* builder) { });
grpc_core::BuildCoreConfiguration(builder); });
builder->channel_init()->RegisterStage( auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
GRPC_SERVER_CHANNEL, 0, CoreEnd2endTest::IncomingStatusOnClient server_status;
[](grpc_core::ChannelStackBuilder* builder) { CoreEnd2endTest::IncomingMetadata server_initial_metadata;
builder->PrependFilter(&test_filter); c.NewBatch(1)
return true; .SendInitialMetadata({})
}); .SendMessage("foo")
}, .SendCloseFromClient()
[config] { test_request(config); }); .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 <limits.h>
#include <string.h>
#include <algorithm> #include <algorithm>
#include <functional>
#include <initializer_list> #include <initializer_list>
#include <memory>
#include <vector> #include <vector>
#include "absl/status/status.h" #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/status.h>
#include <grpc/support/log.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_fwd.h"
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/channel/context.h" #include "src/core/lib/channel/context.h"
#include "src/core/lib/config/core_configuration.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/closure.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
enum { TIMEOUT = 200000 }; 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 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);
}
//****************************************************************************** //******************************************************************************
// Test context filter // Test context filter
@ -189,16 +51,16 @@ struct call_data {
grpc_call_context_element* context; grpc_call_context_element* context;
}; };
static grpc_error_handle init_call_elem(grpc_call_element* elem, grpc_error_handle init_call_elem(grpc_call_element* elem,
const grpc_call_element_args* args) { const grpc_call_element_args* args) {
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
calld->context = args->context; calld->context = args->context;
gpr_log(GPR_INFO, "init_call_elem(): context=%p", args->context); gpr_log(GPR_INFO, "init_call_elem(): context=%p", args->context);
return absl::OkStatus(); return absl::OkStatus();
} }
static void start_transport_stream_op_batch( void start_transport_stream_op_batch(grpc_call_element* elem,
grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { grpc_transport_stream_op_batch* batch) {
call_data* calld = static_cast<call_data*>(elem->call_data); call_data* calld = static_cast<call_data*>(elem->call_data);
// If batch payload context is not null (which will happen in some // If batch payload context is not null (which will happen in some
// cancellation cases), make sure we get the same context here that we // 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); grpc_call_next_op(elem, batch);
} }
static void destroy_call_elem(grpc_call_element* /*elem*/, void destroy_call_elem(grpc_call_element* /*elem*/,
const grpc_call_final_info* /*final_info*/, const grpc_call_final_info* /*final_info*/,
grpc_closure* /*ignored*/) {} grpc_closure* /*ignored*/) {}
static grpc_error_handle init_channel_elem( grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/,
grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { grpc_channel_element_args* /*args*/) {
return absl::OkStatus(); 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, start_transport_stream_op_batch,
nullptr, nullptr,
grpc_channel_next_op, grpc_channel_next_op,
@ -237,31 +99,49 @@ static const grpc_channel_filter test_filter = {
grpc_channel_next_get_info, grpc_channel_next_get_info,
"filter_context"}; "filter_context"};
//****************************************************************************** // Simple request to test that filters see a consistent view of the
// Registration // call context.
// TEST_P(CoreEnd2endTest, FilterContext) {
CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
void filter_context(const CoreTestConfiguration& config) { for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL,
grpc_core::CoreConfiguration::RunWithSpecialConfiguration( GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) {
[](grpc_core::CoreConfiguration::Builder* builder) { builder->channel_init()->RegisterStage(
grpc_core::BuildCoreConfiguration(builder); type, INT_MAX, [](ChannelStackBuilder* builder) {
for (auto type : {GRPC_CLIENT_CHANNEL, GRPC_CLIENT_SUBCHANNEL, // Want to add the filter as close to the end as possible, to
GRPC_CLIENT_DIRECT_CHANNEL, GRPC_SERVER_CHANNEL}) { // make sure that all of the filters work well together.
builder->channel_init()->RegisterStage( // However, we can't add it at the very end, because the
type, INT_MAX, [](grpc_core::ChannelStackBuilder* builder) { // connected channel filter must be the last one. So we add it
// Want to add the filter as close to the end as possible, to // right before the last one.
// make sure that all of the filters work well together. auto it = builder->mutable_stack()->end();
// However, we can't add it at the very end, because the --it;
// connected channel filter must be the last one. So we add it builder->mutable_stack()->insert(it, &test_filter);
// right before the last one. return true;
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)
[config] { test_request(config); }); .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 <limits.h>
#include <string.h>
#include <algorithm> #include <algorithm>
#include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "absl/status/status.h" #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/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.h"
#include "src/core/lib/channel/channel_fwd.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/channel/channel_stack_builder.h"
#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/status_helper.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/closure.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
#include "src/core/lib/promise/arena_promise.h" #include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/promise.h" #include "src/core/lib/promise/promise.h"
#include "src/core/lib/surface/channel_stack_type.h" #include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
enum { TIMEOUT = 200000 }; using ::testing::AnyOf;
static bool g_enable_server_channel_filter = false; namespace grpc_core {
static bool g_enable_client_channel_filter = false; namespace {
static bool g_enable_client_subchannel_filter = false;
static bool g_channel_filter_init_failure = false;
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 // Test filter - always fails to initialize a call
// //
static grpc_error_handle init_call_elem( grpc_error_handle init_call_elem(grpc_call_element* /*elem*/,
grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { const grpc_call_element_args* /*args*/) {
return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"), return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
grpc_core::StatusIntProperty::kRpcStatus, StatusIntProperty::kRpcStatus,
GRPC_STATUS_PERMISSION_DENIED); GRPC_STATUS_PERMISSION_DENIED);
} }
static void destroy_call_elem(grpc_call_element* /*elem*/, void destroy_call_elem(grpc_call_element* /*elem*/,
const grpc_call_final_info* /*final_info*/, const grpc_call_final_info* /*final_info*/,
grpc_closure* /*ignored*/) {} grpc_closure* /*ignored*/) {}
static grpc_error_handle init_channel_elem( grpc_error_handle init_channel_elem(grpc_channel_element* /*elem*/,
grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { grpc_channel_element_args* args) {
if (g_channel_filter_init_failure) { if (args->channel_args.GetBool("channel_init_fails").value_or(false)) {
return grpc_error_set_int( return grpc_error_set_int(
GRPC_ERROR_CREATE("Test channel filter init error"), 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(); 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_call_next_op,
[](grpc_channel_element*, grpc_core::CallArgs, [](grpc_channel_element*, CallArgs,
grpc_core::NextPromiseFactory) NextPromiseFactory) -> ArenaPromise<ServerMetadataHandle> {
-> grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle> { return Immediate(ServerMetadataFromStatus(
return grpc_core::Immediate(grpc_core::ServerMetadataFromStatus(
absl::PermissionDeniedError("access denied"))); absl::PermissionDeniedError("access denied")));
}, },
grpc_channel_next_op, grpc_channel_next_op,
@ -419,63 +95,175 @@ static const grpc_channel_filter test_filter = {
grpc_channel_next_get_info, grpc_channel_next_get_info,
"filter_init_fails"}; "filter_init_fails"};
//****************************************************************************** void RegisterFilter(grpc_channel_stack_type type) {
// Registration 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) { TEST_P(CoreEnd2endTest, DISABLED_ServerFilterChannelInitFails) {
gpr_log(GPR_INFO, "Testing SERVER_CHANNEL filter."); RegisterFilter(GRPC_SERVER_CHANNEL);
g_enable_server_channel_filter = true; InitClient(ChannelArgs());
test_server_channel_filter(config); InitServer(ChannelArgs().Set("channel_init_fails", true));
g_enable_server_channel_filter = false; auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
gpr_log(GPR_INFO, "Testing CLIENT_CHANNEL / CLIENT_DIRECT_CHANNEL filter."); CoreEnd2endTest::IncomingStatusOnClient server_status;
g_enable_client_channel_filter = true; CoreEnd2endTest::IncomingMetadata server_initial_metadata;
test_client_channel_filter(config); c.NewBatch(1)
g_enable_client_channel_filter = false; .SendInitialMetadata({})
// If the client handshake completes before the server handshake and the .SendMessage("hello")
// client is able to send application data before the server handshake .SendCloseFromClient()
// completes, then testing the CLIENT_SUBCHANNEL filter will cause the server .RecvInitialMetadata(server_initial_metadata)
// to freeze waiting for the final handshake message from the client. This .RecvStatusOnClient(server_status);
// handshake message will never arrive because it would have been sent with auto s = RequestCall(101);
// the first application data message, which failed because of the filter. Expect(1, true);
if ((config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL) && Step();
!(config.feature_mask & // Inproc channel returns invalid_argument and other clients return
FEATURE_MASK_DOES_NOT_SUPPORT_CLIENT_HANDSHAKE_COMPLETE_FIRST)) { // unavailable.
gpr_log(GPR_INFO, "Testing CLIENT_SUBCHANNEL filter."); // Windows with sockpair returns unknown.
g_enable_client_subchannel_filter = true; EXPECT_THAT(server_status.status(),
test_client_subchannel_filter(config); AnyOf(GRPC_STATUS_UNKNOWN, GRPC_STATUS_UNAVAILABLE,
g_enable_client_subchannel_filter = false; 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) { TEST_P(CoreClientChannelTest, SubchannelFilterCallInitFails) {
grpc_core::CoreConfiguration::RunWithSpecialConfiguration( RegisterFilter(GRPC_CLIENT_SUBCHANNEL);
[](grpc_core::CoreConfiguration::Builder* builder) { auto c = NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
grpc_core::BuildCoreConfiguration(builder); CoreEnd2endTest::IncomingStatusOnClient server_status;
auto register_stage = [builder](grpc_channel_stack_type type, CoreEnd2endTest::IncomingMetadata server_initial_metadata;
bool* enable) { CoreEnd2endTest::IncomingMessage server_message;
builder->channel_init()->RegisterStage( c.NewBatch(1)
type, INT_MAX, [enable](grpc_core::ChannelStackBuilder* builder) { .SendInitialMetadata({})
if (!*enable) return true; .SendMessage("hello")
// Want to add the filter as close to the end as possible, .SendCloseFromClient()
// to make sure that all of the filters work well together. .RecvInitialMetadata(server_initial_metadata)
// However, we can't add it at the very end, because either the .RecvStatusOnClient(server_status);
// client_channel filter or connected_channel filter must be the Expect(1, true);
// last one. So we add it right before the last one. Step();
auto it = builder->mutable_stack()->end(); EXPECT_EQ(server_status.status(), GRPC_STATUS_PERMISSION_DENIED);
--it; EXPECT_EQ(server_status.message(), "access denied");
builder->mutable_stack()->insert(it, &test_filter); // Create a new call. (The first call uses a different code path in
return true; // 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();
register_stage(GRPC_SERVER_CHANNEL, &g_enable_server_channel_filter); CoreEnd2endTest::IncomingStatusOnClient server_status2;
register_stage(GRPC_CLIENT_CHANNEL, &g_enable_client_channel_filter); CoreEnd2endTest::IncomingMetadata server_initial_metadata2;
register_stage(GRPC_CLIENT_SUBCHANNEL, CoreEnd2endTest::IncomingMessage server_message2;
&g_enable_client_subchannel_filter); c2.NewBatch(2)
register_stage(GRPC_CLIENT_DIRECT_CHANNEL, .SendInitialMetadata({})
&g_enable_client_channel_filter); .SendMessage("hi again")
}, .SendCloseFromClient()
[&config] { filter_init_fails_internal(config); }); .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/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 "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.h" #include "test/core/end2end/end2end_tests.h"
#include "test/core/util/test_config.h"
static std::unique_ptr<CoreTestFixture> begin_test( namespace grpc_core {
const CoreTestConfiguration& config, const char* test_name, namespace {
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 which should be filtered // Request/response with metadata which should be filtered
static void test_request_response_with_metadata_to_be_filtered( void TestRequestResponseWithMetadataToBeFiltered(
const CoreTestConfiguration& config, const char* filtered_md_key, CoreEnd2endTest& test, absl::string_view filtered_md_key,
const char* filter_md_value) { absl::string_view filter_md_value) {
grpc_call* c; auto c = test.NewClientCall("/foo").Timeout(Duration::Seconds(5)).Create();
grpc_call* s;
grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"), CoreEnd2endTest::IncomingMetadata server_initial_metadata;
grpc_slice_from_static_string("val1"), CoreEnd2endTest::IncomingStatusOnClient server_status;
{{nullptr, nullptr, nullptr, nullptr}}}, c.NewBatch(1)
{grpc_slice_from_static_string(filtered_md_key), .SendInitialMetadata(
grpc_slice_from_static_string(filter_md_value), {{"key1", "val1"}, {filtered_md_key, filter_md_value}})
{{nullptr, nullptr, nullptr, nullptr}}}}; .SendCloseFromClient()
grpc_metadata meta_s[2] = {{grpc_slice_from_static_string("key2"), .RecvInitialMetadata(server_initial_metadata)
grpc_slice_from_static_string("val2"), .RecvStatusOnClient(server_status);
{{nullptr, nullptr, nullptr, nullptr}}},
{grpc_slice_from_static_string(filtered_md_key), auto s = test.RequestCall(101);
grpc_slice_from_static_string(filter_md_value),
{{nullptr, nullptr, nullptr, nullptr}}}}; test.Expect(101, true);
auto f = test.Step();
begin_test(config, "test_request_response_with_metadata_to_be_filtered",
nullptr, nullptr); s.NewBatch(102).SendInitialMetadata(
grpc_core::CqVerifier cqv(f->cq()); {{"key2", "val2"}, {filtered_md_key, filter_md_value}});
grpc_op ops[6]; test.Expect(102, true);
grpc_op* op; test.Step();
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv; CoreEnd2endTest::IncomingCloseOnServer client_close;
grpc_metadata_array request_metadata_recv; s.NewBatch(103)
grpc_call_details call_details; .RecvCloseOnServer(client_close)
grpc_status_code status; .SendStatusFromServer(GRPC_STATUS_OK, "xyz", {});
grpc_call_error error; test.Expect(103, true);
grpc_slice details; test.Expect(1, true);
int was_cancelled = 2; test.Step();
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5); EXPECT_EQ(server_status.status(), GRPC_STATUS_OK);
c = grpc_channel_create_call(f->client(), nullptr, GRPC_PROPAGATE_DEFAULTS, EXPECT_EQ(server_status.message(), "xyz");
f->cq(), grpc_slice_from_static_string("/foo"), EXPECT_EQ(s.method(), "/foo");
nullptr, deadline, nullptr); EXPECT_FALSE(client_close.was_cancelled());
GPR_ASSERT(c); EXPECT_EQ(s.GetInitialMetadata("key1"), "val1");
EXPECT_EQ(s.GetInitialMetadata(filtered_md_key), absl::nullopt);
grpc_metadata_array_init(&initial_metadata_recv); EXPECT_EQ(server_initial_metadata.Get("key2"), "val2");
grpc_metadata_array_init(&trailing_metadata_recv); EXPECT_EQ(server_initial_metadata.Get(filtered_md_key), absl::nullopt);
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 filtered_metadata(const CoreTestConfiguration& config) { TEST_P(CoreEnd2endTest, ContentLengthIsFiltered) {
test_request_response_with_metadata_to_be_filtered(config, "content-length", TestRequestResponseWithMetadataToBeFiltered(*this, "content-length", "45");
"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/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 "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/end2end_tests.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 // shutdown and destroy the server
grpc_server_shutdown_and_notify(f->server(), f->cq(), ShutdownServerAndNotify(200);
grpc_core::CqVerifier::tag(0xdead)); Step();
cqv.VerifyEmpty(); CoreEnd2endTest::IncomingCloseOnServer client_close;
s.NewBatch(102)
memset(ops, 0, sizeof(ops)); .SendInitialMetadata({})
op = ops; .SendStatusFromServer(GRPC_STATUS_UNIMPLEMENTED, "xyz", {})
op->op = GRPC_OP_SEND_INITIAL_METADATA; .RecvCloseOnServer(client_close);
op->data.send_initial_metadata.count = 0; Expect(102, true);
op->flags = 0; Expect(200, true);
op->reserved = nullptr; Expect(1, true);
op++; Step();
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0; EXPECT_EQ(server_status.status(), GRPC_STATUS_UNIMPLEMENTED);
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; EXPECT_EQ(s.method(), "/foo");
grpc_slice status_details = grpc_slice_from_static_string("xyz"); EXPECT_FALSE(client_close.was_cancelled());
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);
} }
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